orval 0.0.1__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.
- orval-0.0.1/PKG-INFO +76 -0
- orval-0.0.1/README.md +62 -0
- orval-0.0.1/pyproject.toml +137 -0
- orval-0.0.1/src/orval/__init__.py +15 -0
- orval-0.0.1/src/orval/arrays.py +12 -0
- orval-0.0.1/src/orval/datetimes.py +12 -0
- orval-0.0.1/src/orval/py.typed +0 -0
- orval-0.0.1/src/orval/strings.py +61 -0
- orval-0.0.1/src/orval/utils.py +43 -0
orval-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: orval
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: A Python package that contains a small set of convenient python functions
|
|
5
|
+
Home-page: https://github.com/lukin0110/orval/
|
|
6
|
+
License: Proprietary
|
|
7
|
+
Requires-Python: >=3.13.0,<4.0
|
|
8
|
+
Classifier: License :: Other/Proprietary License
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
+
Project-URL: Repository, https://github.com/lukin0110/orval/
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
[](https://github.com/lukin0110/orval/actions)
|
|
15
|
+
|
|
16
|
+
# Orval
|
|
17
|
+
|
|
18
|
+
A Python package that contains a small set of convenient python functions.
|
|
19
|
+
|
|
20
|
+
## 🚀 Using
|
|
21
|
+
|
|
22
|
+
To install this package, run:
|
|
23
|
+
```bash
|
|
24
|
+
pip install orval
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
## 🧑💻 Contributing
|
|
29
|
+
|
|
30
|
+
<details>
|
|
31
|
+
<summary>Prerequisites</summary>
|
|
32
|
+
|
|
33
|
+
<details>
|
|
34
|
+
<summary>1. Install Docker</summary>
|
|
35
|
+
|
|
36
|
+
1. Go to [Docker](https://www.docker.com/get-started), download and install docker.
|
|
37
|
+
2. [Configure Docker to use the BuildKit build system](https://docs.docker.com/build/buildkit/#getting-started). On macOS and Windows, BuildKit is enabled by default in Docker Desktop.
|
|
38
|
+
|
|
39
|
+
</details>
|
|
40
|
+
|
|
41
|
+
<details>
|
|
42
|
+
<summary>2. Install VS Code</summary>
|
|
43
|
+
|
|
44
|
+
Go to [VS Code](https://code.visualstudio.com/), download and install VS Code.
|
|
45
|
+
</details>
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
</details>
|
|
49
|
+
|
|
50
|
+
#### 1. Open DevContainer with VS Code
|
|
51
|
+
Open this repository with VS Code, and run <kbd>Ctrl/⌘</kbd> + <kbd>⇧</kbd> + <kbd>P</kbd> → _Dev Containers: Reopen in Container_.
|
|
52
|
+
|
|
53
|
+
The following commands can be used inside a DevContainer.
|
|
54
|
+
|
|
55
|
+
#### 2. Run linters
|
|
56
|
+
```bash
|
|
57
|
+
poe lint
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
#### 3. Run tests
|
|
61
|
+
```bash
|
|
62
|
+
poe test
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
#### 4. Update poetry lock file
|
|
66
|
+
```bash
|
|
67
|
+
poetry lock --no-update
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
See how to develop with [PyCharm or any other IDE](https://github.com/lukin0110/poetry-copier/tree/main/docs/ide.md).
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
️⚡️ Scaffolded with [Poetry Copier](https://github.com/lukin0110/poetry-copier/).\
|
|
75
|
+
🛠️ [Open an issue](https://github.com/lukin0110/poetry-copier/issues/new) if you have any questions or suggestions.
|
|
76
|
+
|
orval-0.0.1/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
[](https://github.com/lukin0110/orval/actions)
|
|
2
|
+
|
|
3
|
+
# Orval
|
|
4
|
+
|
|
5
|
+
A Python package that contains a small set of convenient python functions.
|
|
6
|
+
|
|
7
|
+
## 🚀 Using
|
|
8
|
+
|
|
9
|
+
To install this package, run:
|
|
10
|
+
```bash
|
|
11
|
+
pip install orval
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## 🧑💻 Contributing
|
|
16
|
+
|
|
17
|
+
<details>
|
|
18
|
+
<summary>Prerequisites</summary>
|
|
19
|
+
|
|
20
|
+
<details>
|
|
21
|
+
<summary>1. Install Docker</summary>
|
|
22
|
+
|
|
23
|
+
1. Go to [Docker](https://www.docker.com/get-started), download and install docker.
|
|
24
|
+
2. [Configure Docker to use the BuildKit build system](https://docs.docker.com/build/buildkit/#getting-started). On macOS and Windows, BuildKit is enabled by default in Docker Desktop.
|
|
25
|
+
|
|
26
|
+
</details>
|
|
27
|
+
|
|
28
|
+
<details>
|
|
29
|
+
<summary>2. Install VS Code</summary>
|
|
30
|
+
|
|
31
|
+
Go to [VS Code](https://code.visualstudio.com/), download and install VS Code.
|
|
32
|
+
</details>
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
</details>
|
|
36
|
+
|
|
37
|
+
#### 1. Open DevContainer with VS Code
|
|
38
|
+
Open this repository with VS Code, and run <kbd>Ctrl/⌘</kbd> + <kbd>⇧</kbd> + <kbd>P</kbd> → _Dev Containers: Reopen in Container_.
|
|
39
|
+
|
|
40
|
+
The following commands can be used inside a DevContainer.
|
|
41
|
+
|
|
42
|
+
#### 2. Run linters
|
|
43
|
+
```bash
|
|
44
|
+
poe lint
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
#### 3. Run tests
|
|
48
|
+
```bash
|
|
49
|
+
poe test
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
#### 4. Update poetry lock file
|
|
53
|
+
```bash
|
|
54
|
+
poetry lock --no-update
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
See how to develop with [PyCharm or any other IDE](https://github.com/lukin0110/poetry-copier/tree/main/docs/ide.md).
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
️⚡️ Scaffolded with [Poetry Copier](https://github.com/lukin0110/poetry-copier/).\
|
|
62
|
+
🛠️ [Open an issue](https://github.com/lukin0110/poetry-copier/issues/new) if you have any questions or suggestions.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
[tool.poetry] # https://python-poetry.org/docs/pyproject/
|
|
2
|
+
name = "orval"
|
|
3
|
+
version = "0.0.1"
|
|
4
|
+
description = "A Python package that contains a small set of convenient python functions"
|
|
5
|
+
authors = []
|
|
6
|
+
license = "Proprietary"
|
|
7
|
+
readme = "README.md"
|
|
8
|
+
repository = "https://github.com/lukin0110/orval/"
|
|
9
|
+
|
|
10
|
+
[build-system] # https://python-poetry.org/docs/pyproject/#poetry-and-pep-517
|
|
11
|
+
requires = ["poetry-core>=1.0.0"]
|
|
12
|
+
build-backend = "poetry.core.masonry.api"
|
|
13
|
+
|
|
14
|
+
[tool.poetry.dependencies] # https://python-poetry.org/docs/dependency-specification/
|
|
15
|
+
python = ">=3.13.0,<4.0"
|
|
16
|
+
|
|
17
|
+
[tool.poetry.group.dev.dependencies] # https://python-poetry.org/docs/master/managing-dependencies/
|
|
18
|
+
coverage = { extras = ["toml"], version = ">=7.4.1" }
|
|
19
|
+
ipython = ">=8.29.0"
|
|
20
|
+
mypy = "1.13.0"
|
|
21
|
+
poethepoet = ">=0.29.0"
|
|
22
|
+
pre-commit = ">=4.0.1"
|
|
23
|
+
pytest = ">=8.3.3"
|
|
24
|
+
pytest-clarity = ">=1.0.1"
|
|
25
|
+
pytest-mock = ">=3.14.0"
|
|
26
|
+
ruff = ">=0.7.2"
|
|
27
|
+
safety = ">=2.3.5,!=2.3.5"
|
|
28
|
+
shellcheck-py = ">=0.10.0"
|
|
29
|
+
typeguard = ">=4.4.1"
|
|
30
|
+
|
|
31
|
+
[[tool.poetry.source]] # https://python-poetry.org/docs/repositories/
|
|
32
|
+
name = "pypi"
|
|
33
|
+
priority = "primary"
|
|
34
|
+
|
|
35
|
+
[tool.coverage.report] # https://coverage.readthedocs.io/en/latest/config.html#report
|
|
36
|
+
# TODO: please raise the bar :)
|
|
37
|
+
fail_under = 0
|
|
38
|
+
precision = 1
|
|
39
|
+
show_missing = true
|
|
40
|
+
skip_covered = true
|
|
41
|
+
|
|
42
|
+
[tool.coverage.run] # https://coverage.readthedocs.io/en/latest/config.html#run
|
|
43
|
+
branch = true
|
|
44
|
+
command_line = "--module pytest"
|
|
45
|
+
data_file = "reports/.coverage"
|
|
46
|
+
source = ["src"]
|
|
47
|
+
|
|
48
|
+
[tool.coverage.xml] # https://coverage.readthedocs.io/en/latest/config.html#xml
|
|
49
|
+
output = "reports/coverage.xml"
|
|
50
|
+
|
|
51
|
+
[tool.mypy] # https://mypy.readthedocs.io/en/latest/config_file.html
|
|
52
|
+
junit_xml = "reports/mypy.xml"
|
|
53
|
+
strict = true
|
|
54
|
+
disallow_subclassing_any = false
|
|
55
|
+
disallow_untyped_decorators = false
|
|
56
|
+
explicit_package_bases = true
|
|
57
|
+
ignore_missing_imports = true
|
|
58
|
+
pretty = true
|
|
59
|
+
show_column_numbers = true
|
|
60
|
+
show_error_codes = true
|
|
61
|
+
show_error_context = true
|
|
62
|
+
warn_unreachable = true
|
|
63
|
+
mypy_path = "src"
|
|
64
|
+
|
|
65
|
+
[tool.pytest.ini_options] # https://docs.pytest.org/en/latest/reference/reference.html#ini-options-ref
|
|
66
|
+
addopts = "--color=yes --doctest-modules --exitfirst --failed-first --strict-config --strict-markers --typeguard-packages=orval --verbosity=2 --junitxml=reports/pytest.xml"
|
|
67
|
+
filterwarnings = ["error", "ignore::DeprecationWarning"]
|
|
68
|
+
testpaths = ["src", "tests"]
|
|
69
|
+
xfail_strict = true
|
|
70
|
+
log_file_level = "info"
|
|
71
|
+
pythonpath = "src"
|
|
72
|
+
|
|
73
|
+
[tool.ruff] # https://github.com/charliermarsh/ruff
|
|
74
|
+
fix = true
|
|
75
|
+
line-length = 120
|
|
76
|
+
src = ["src", "tests"]
|
|
77
|
+
target-version = "py313"
|
|
78
|
+
force-exclude = true # https://docs.astral.sh/ruff/settings/#force-exclude
|
|
79
|
+
preview = true # https://docs.astral.sh/ruff/preview/
|
|
80
|
+
|
|
81
|
+
[tool.ruff.lint] # https://github.com/charliermarsh/ruff
|
|
82
|
+
ignore = ["FBT002", "G004", "D203", "D213", "E501", "EM101", "EM102", "FBT001", "ISC001", "RET504", "S101", "TRY003", "TRY300", "W505"]
|
|
83
|
+
select = ["A", "ASYNC", "B", "BLE", "C4", "C90", "D", "DTZ", "E", "EM", "ERA", "F", "FBT", "FLY", "FURB", "G", "I", "ICN", "INP", "INT", "ISC", "LOG", "N", "NPY", "PERF", "PGH", "PIE", "PLC", "PLE", "PLR", "PLW", "PT", "PTH", "PYI", "RET", "RSE", "RUF", "S", "SIM", "SLF", "SLOT", "T10", "T20", "TCH", "TID", "TRY", "UP", "W", "YTT"]
|
|
84
|
+
unfixable = ["ERA001", "F401", "F841", "T201", "T203"] # https://docs.astral.sh/ruff/settings/#unfixable
|
|
85
|
+
|
|
86
|
+
[tool.ruff.lint.extend-per-file-ignores] # https://docs.astral.sh/ruff/settings/#extend-per-file-ignores
|
|
87
|
+
# Ignore missing __init__.py files in tests.
|
|
88
|
+
"tests/*" = ["INP001", "PLR2004"]
|
|
89
|
+
|
|
90
|
+
[tool.ruff.lint.flake8-tidy-imports]
|
|
91
|
+
# Disallow all relative imports.
|
|
92
|
+
ban-relative-imports = "all"
|
|
93
|
+
|
|
94
|
+
[tool.ruff.lint.mccabe]
|
|
95
|
+
max-complexity = 10
|
|
96
|
+
|
|
97
|
+
[tool.ruff.lint.pep8-naming]
|
|
98
|
+
# Allow Pydantic's `@validator` decorator to trigger class method treatment.
|
|
99
|
+
classmethod-decorators = ["classmethod", "pydantic.validator", "pydantic.root_validator"]
|
|
100
|
+
|
|
101
|
+
[tool.ruff.lint.pycodestyle]
|
|
102
|
+
max-doc-length = 100
|
|
103
|
+
|
|
104
|
+
[tool.ruff.lint.pydocstyle]
|
|
105
|
+
convention = "numpy"
|
|
106
|
+
|
|
107
|
+
[tool.poe.tasks] # https://poethepoet.natn.io/index.html
|
|
108
|
+
[tool.poe.tasks.lint]
|
|
109
|
+
help = "Lint this package"
|
|
110
|
+
|
|
111
|
+
[[tool.poe.tasks.lint.sequence]]
|
|
112
|
+
shell = '[ -d ".git" ] || { echo "\n\\033[0;31mGit is not initialized in this directory. Please run \"git init\" to fix linting.\\033[0m\n"; exit 1; }'
|
|
113
|
+
|
|
114
|
+
[[tool.poe.tasks.lint.sequence]]
|
|
115
|
+
cmd = """
|
|
116
|
+
pre-commit run
|
|
117
|
+
--all-files
|
|
118
|
+
--color always
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
[tool.poe.tasks.safety]
|
|
123
|
+
help = "Run safety checks on this package"
|
|
124
|
+
shell = "safety check --continue-on-error --full-report"
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
[tool.poe.tasks.test]
|
|
128
|
+
help = "Test this package"
|
|
129
|
+
|
|
130
|
+
[[tool.poe.tasks.test.sequence]]
|
|
131
|
+
cmd = "coverage run"
|
|
132
|
+
|
|
133
|
+
[[tool.poe.tasks.test.sequence]]
|
|
134
|
+
cmd = "coverage report"
|
|
135
|
+
|
|
136
|
+
[[tool.poe.tasks.test.sequence]]
|
|
137
|
+
cmd = "coverage xml"
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Orval package."""
|
|
2
|
+
|
|
3
|
+
from orval.datetimes import utcnow
|
|
4
|
+
from orval.strings import camel_case, kebab_case, pascal_case, slugify, snake_case
|
|
5
|
+
from orval.utils import timing
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"camel_case",
|
|
9
|
+
"kebab_case",
|
|
10
|
+
"pascal_case",
|
|
11
|
+
"slugify",
|
|
12
|
+
"snake_case",
|
|
13
|
+
"timing",
|
|
14
|
+
"utcnow",
|
|
15
|
+
]
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""Array utilities."""
|
|
2
|
+
|
|
3
|
+
from typing import TypeVar
|
|
4
|
+
|
|
5
|
+
T = TypeVar("T")
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def chunkify(seq: list[T], s: int) -> list[list[T]]:
|
|
9
|
+
"""Break a list into chunks of size S."""
|
|
10
|
+
if s < 1:
|
|
11
|
+
raise ValueError(f"Size must be > 0, invalid value {s}")
|
|
12
|
+
return [seq[pos : pos + s] for pos in range(0, len(seq), s)]
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""Datetime utilities."""
|
|
2
|
+
|
|
3
|
+
import datetime
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def utcnow() -> datetime.datetime:
|
|
7
|
+
"""Generate now as a datetime with UTC time zone info.
|
|
8
|
+
|
|
9
|
+
The `datetime.datetime.utcnow()` function from the standard library does not include time zone information by
|
|
10
|
+
default. https://docs.python.org/3/library/datetime.html#datetime.datetime.now
|
|
11
|
+
"""
|
|
12
|
+
return datetime.datetime.now(tz=datetime.UTC)
|
|
File without changes
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""String utilities."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
import unicodedata
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def slugify(value: str, allow_unicode: bool = False) -> str:
|
|
8
|
+
"""Create a slug from a given string.
|
|
9
|
+
|
|
10
|
+
Normalize strings to a 'slug'. Can be used to format URL's or resource names (eg: Database name).
|
|
11
|
+
|
|
12
|
+
Convert to ASCII if 'allow_unicode' is False.
|
|
13
|
+
Convert any single or consecutive spaces, dots or hyphens to a single hyphen.
|
|
14
|
+
Remove characters that aren't alphanumerics, underscores, or hyphens.
|
|
15
|
+
Convert to lowercase.
|
|
16
|
+
Strip leading and trailing whitespace.
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
----------
|
|
20
|
+
value
|
|
21
|
+
Input string to transform.
|
|
22
|
+
allow_unicode
|
|
23
|
+
The output may contain unicode characters.
|
|
24
|
+
|
|
25
|
+
Returns
|
|
26
|
+
-------
|
|
27
|
+
str
|
|
28
|
+
Returns a transformed string.
|
|
29
|
+
"""
|
|
30
|
+
if allow_unicode:
|
|
31
|
+
value = unicodedata.normalize("NFKC", value)
|
|
32
|
+
else:
|
|
33
|
+
value = unicodedata.normalize("NFKD", value).encode("ascii", "ignore").decode("ascii")
|
|
34
|
+
value = re.sub(r"[^\w\s\-.]", "", value).strip().lower()
|
|
35
|
+
return re.sub(r"[\s\-.]+", "-", value)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def camel_case(string: str) -> str:
|
|
39
|
+
"""Convert a string to camelCase."""
|
|
40
|
+
input_ = string.strip()
|
|
41
|
+
words = input_.split(" ")
|
|
42
|
+
camel_case_words = [words[0].lower()] + [word.capitalize() for word in words[1:]]
|
|
43
|
+
return "".join(camel_case_words)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def kebab_case(string: str) -> str:
|
|
47
|
+
"""Convert a string to kebab-case."""
|
|
48
|
+
input_ = string.strip().lower()
|
|
49
|
+
return input_.replace(" ", "-")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def pascal_case(string: str) -> str:
|
|
53
|
+
"""Convert a string to PascalCase."""
|
|
54
|
+
words = string.split()
|
|
55
|
+
return "".join(word.capitalize() for word in words)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def snake_case(string: str) -> str:
|
|
59
|
+
"""Convert a string to snake_case."""
|
|
60
|
+
input_ = string.strip().lower()
|
|
61
|
+
return input_.replace(" ", "_")
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Utilities."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import time
|
|
5
|
+
from collections.abc import Callable
|
|
6
|
+
from functools import partial
|
|
7
|
+
from typing import Any, TypeVar
|
|
8
|
+
|
|
9
|
+
R = TypeVar("R")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def timing(func: Callable[..., R] | None = None, level: int = logging.INFO) -> Any:
|
|
13
|
+
"""Log the elapsed time of a function.
|
|
14
|
+
|
|
15
|
+
Decorator can be used with or without arguments. Eg: `@timing` or `@timing(level=logging.DEBUG)`.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
func
|
|
20
|
+
The wrapped function to log the elapsed time of.
|
|
21
|
+
level
|
|
22
|
+
Log level to user. Default: INFO.
|
|
23
|
+
|
|
24
|
+
Returns
|
|
25
|
+
-------
|
|
26
|
+
Any
|
|
27
|
+
The function wrapped to log timing.
|
|
28
|
+
"""
|
|
29
|
+
if func is None:
|
|
30
|
+
return partial(timing, level=level)
|
|
31
|
+
|
|
32
|
+
def wrapper(
|
|
33
|
+
*args: list[Any],
|
|
34
|
+
**kwargs: dict[str, Any],
|
|
35
|
+
) -> Any:
|
|
36
|
+
"""Log elapsed time of the wrapped function."""
|
|
37
|
+
start = time.perf_counter()
|
|
38
|
+
result = func(*args, **kwargs)
|
|
39
|
+
end = time.perf_counter()
|
|
40
|
+
logging.getLogger(__name__).log(level, f"Timing for '{func.__name__}': {end - start:.3f}s")
|
|
41
|
+
return result
|
|
42
|
+
|
|
43
|
+
return wrapper
|