crypticorn-utils 0.1.0rc1__py3-none-any.whl → 1.0.0rc1__py3-none-any.whl

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.4
2
2
  Name: crypticorn_utils
3
- Version: 0.1.0rc1
3
+ Version: 1.0.0rc1
4
4
  Summary: Shared utilities for the Crypticorn APIs
5
5
  Author-email: Crypticorn <timon@crypticorn.com>
6
6
  License-Expression: MIT
@@ -11,20 +11,17 @@ Classifier: Topic :: Scientific/Engineering
11
11
  Classifier: Development Status :: 4 - Beta
12
12
  Classifier: Intended Audience :: Developers
13
13
  Classifier: Operating System :: OS Independent
14
- Classifier: Programming Language :: Python :: 3.9
15
- Classifier: Programming Language :: Python :: 3.10
16
14
  Classifier: Programming Language :: Python :: 3.11
17
15
  Classifier: Programming Language :: Python :: 3.12
18
16
  Classifier: Programming Language :: Python :: 3.13
19
17
  Classifier: Typing :: Typed
20
- Requires-Python: >=3.9
18
+ Requires-Python: >=3.11
21
19
  Description-Content-Type: text/markdown
22
20
  License-File: LICENSE
23
21
  Requires-Dist: fastapi<1.0.0,>=0.115.0
24
22
  Requires-Dist: click<9.0.0,>=8.0.0
25
23
  Requires-Dist: psutil<8.0.0,>=7.0.0
26
24
  Requires-Dist: setuptools<81.0.0,>=80.0.0
27
- Requires-Dist: strenum
28
25
  Requires-Dist: prometheus-client<1.0.0,>=0.22.0
29
26
  Provides-Extra: dev
30
27
  Requires-Dist: build; extra == "dev"
@@ -68,6 +65,24 @@ This module serves as a central place for providing utilities for our python bac
68
65
 
69
66
  <!-- changelog-insertion -->
70
67
 
68
+ ## v1.0.0-rc.1 (2025-07-17)
69
+
70
+ ### Build System
71
+
72
+ - Deployment config for v1 branches
73
+ ([`b94d9e7`](https://github.com/crypticorn-ai/util-libraries/commit/b94d9e72616e398760993f6ebb1a6fd876a95802))
74
+
75
+ BREAKING CHANGE: - removed: mixins, openapi and both router modules; CLI; Scope Enum class;
76
+ `throw_if_none` and `throw_if_falsy`; all deprecation warnings - reworked: exceptions and error
77
+ modules
78
+
79
+ - Mark packaage as typed
80
+ ([`69544a8`](https://github.com/crypticorn-ai/util-libraries/commit/69544a8709f4d55850e107031b82d91c28334b3c))
81
+
82
+ - Remove support for python versions 3.9 and 3.10
83
+ ([`80b8543`](https://github.com/crypticorn-ai/util-libraries/commit/80b8543ed5559a0de421aef4e2382193e930751a))
84
+
85
+
71
86
  ## v0.1.0-rc.1 (2025-06-23)
72
87
 
73
88
  ### Documentation
@@ -0,0 +1,21 @@
1
+ crypticorn_utils/__init__.py,sha256=hZhTmMU8-1oY382nJH-l4B7jH8nQzxFeMaLzEXC-1hc,1406
2
+ crypticorn_utils/_migration.py,sha256=2WfApGi5w46SDT0GjUA0Iz8KuDTSwrPNGJCyG9AbLb4,519
3
+ crypticorn_utils/ansi_colors.py,sha256=ts49UtfTy-c0uvlGwb3wE-jE_GbXvSBSfzwrDlNi0HE,1331
4
+ crypticorn_utils/auth.py,sha256=23b3oj-A0h44wucGSC6n1R44ytoNalW9jcjE-nhP2OU,14518
5
+ crypticorn_utils/decorators.py,sha256=chsbF27_q3hC0egBaZLfv2vcqUcBSfQXRkLi3Ewb-20,1063
6
+ crypticorn_utils/enums.py,sha256=QftU5ebtdGD9b7mBPoWDVkuaJEoxiFgt9ew_-PcvCZc,1330
7
+ crypticorn_utils/errors.py,sha256=PYYB-qeL9PCE8m5XyRXfkGGjsPgX4Vc_4Ii1-7yeW50,771
8
+ crypticorn_utils/exceptions.py,sha256=Rv1OYZp4CsK6VAtc4nhpyL28fK2aVWkFYSdECmJK4VE,9305
9
+ crypticorn_utils/logging.py,sha256=ORt-uZ47kqnbgtp6rJfcVvxy_KYlfHTyuWM4UF755s4,3968
10
+ crypticorn_utils/metrics.py,sha256=3eMt1DMFIIm835YYqOl41cpzeRA8nxl3nHcnQcTgZeA,866
11
+ crypticorn_utils/middleware.py,sha256=CPp_vPwm7LXNt71uFBReVwUrqJqur6xUErWurMx18cw,2902
12
+ crypticorn_utils/pagination.py,sha256=06shym28tfD-Cc9EPk2W7K2GHqUj2Kk4ShQ0BrKCDWY,11432
13
+ crypticorn_utils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ crypticorn_utils/utils.py,sha256=tFFgMjkitY4AtHkyfyb0Nu87u9gIAPwga6SML3skBZk,1459
15
+ crypticorn_utils/warnings.py,sha256=52gLJs-1YJiJebahY2hDkyN_reCY21YXzZfIOCHBYWg,1775
16
+ crypticorn_utils-1.0.0rc1.dist-info/licenses/LICENSE,sha256=DEU3BF944yFmGthgeH70d9TA3lB9hGfvwTtu6VDYPO0,1857
17
+ crypticorn_utils-1.0.0rc1.dist-info/METADATA,sha256=p1fcztHRmMjaUFoA5QguWqC5NhGHSxuJjVMjm9gTWSw,4578
18
+ crypticorn_utils-1.0.0rc1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
19
+ crypticorn_utils-1.0.0rc1.dist-info/entry_points.txt,sha256=G4yWDll7v_Kb4uemqI-_qTKXHvs10R4mD7hNuD-biv4,71
20
+ crypticorn_utils-1.0.0rc1.dist-info/top_level.txt,sha256=jLPvdxnI36RPf8TX3aZhl35OSd721xEYyFSEeQKF6Ic,17
21
+ crypticorn_utils-1.0.0rc1.dist-info/RECORD,,
@@ -12,4 +12,4 @@ Changes to this agreement may be made without notice, and it is the user's respo
12
12
 
13
13
  If any provision of this license agreement is held to be invalid or unenforceable under applicable law, the remaining provisions will continue in full force and effect. Crypticorn's failure to enforce any provision of this agreement does not constitute a waiver of its right to do so in the future.
14
14
 
15
- This agreement is written in English. In the event of any discrepancy between the English version and any translation, the English version shall prevail.
15
+ This agreement is written in English. In the event of any discrepancy between the English version and any translation, the English version shall prevail.
@@ -1,4 +0,0 @@
1
- from crypticorn.cli.init import init_group
2
- from crypticorn.cli.version import version
3
-
4
- __all__ = ["init_group", "version"]
@@ -1,17 +0,0 @@
1
- # crypticorn/cli.py
2
-
3
- import click
4
- from crypticorn.cli import init_group, version
5
-
6
-
7
- @click.group()
8
- def cli():
9
- """🧙 Crypticorn CLI — magic for our microservices."""
10
- pass
11
-
12
-
13
- cli.add_command(init_group, name="init")
14
- cli.add_command(version, name="version")
15
-
16
- if __name__ == "__main__":
17
- cli()
@@ -1,127 +0,0 @@
1
- import click
2
- from pathlib import Path
3
- import subprocess
4
- import importlib.resources
5
- import crypticorn.cli.templates as templates
6
-
7
-
8
- def get_git_root() -> Path:
9
- """Get the root directory of the git repository."""
10
- try:
11
- return Path(
12
- subprocess.check_output(
13
- ["git", "rev-parse", "--show-toplevel"], text=True
14
- ).strip()
15
- )
16
- except Exception:
17
- return Path.cwd()
18
-
19
-
20
- def copy_template(template_name: str, target_path: Path):
21
- """Copy a template file to the target path."""
22
- with importlib.resources.files(templates).joinpath(template_name).open(
23
- "r"
24
- ) as template_file:
25
- content = template_file.read()
26
-
27
- target_path.parent.mkdir(parents=True, exist_ok=True)
28
- with target_path.open("w") as f:
29
- f.write(content)
30
-
31
- click.secho(f"✅ Created: {target_path}", fg="green")
32
-
33
-
34
- def check_file_exists(path: Path, force: bool):
35
- if path.exists() and not force:
36
- click.secho("File already exists, use --force / -f to overwrite", fg="red")
37
- return False
38
- return True
39
-
40
-
41
- @click.group()
42
- def init_group():
43
- """Initialize files like CI configs, linters, etc."""
44
- pass
45
-
46
-
47
- @init_group.command("ruff")
48
- @click.option("-f", "--force", is_flag=True, help="Force overwrite the ruff.yml")
49
- def init_ruff(force):
50
- """Add .github/workflows/ruff.yml"""
51
- root = get_git_root()
52
- target = root / ".github/workflows/ruff.yml"
53
- if target.exists() and not force:
54
- click.secho("File already exists, use --force / -f to overwrite", fg="red")
55
- return
56
- copy_template("ruff.yml", target)
57
-
58
-
59
- @init_group.command("docker")
60
- @click.option(
61
- "-o", "--output", type=click.Path(), help="Custom output path for the Dockerfile"
62
- )
63
- @click.option("-f", "--force", is_flag=True, help="Force overwrite the Dockerfile")
64
- def init_docker(output, force):
65
- """Add Dockerfile"""
66
- root = get_git_root()
67
- if output and Path(output).is_file():
68
- click.secho("Output path is a file, please provide a directory path", fg="red")
69
- return
70
- target = (Path(output) if output else root) / "Dockerfile"
71
- if not check_file_exists(target, force):
72
- return
73
- copy_template("Dockerfile", target)
74
- click.secho("Make sure to update the Dockerfile", fg="yellow")
75
-
76
-
77
- @init_group.command("auth")
78
- @click.option(
79
- "-o", "--output", type=click.Path(), help="Custom output path for the auth handler"
80
- )
81
- @click.option("-f", "--force", is_flag=True, help="Force overwrite the auth handler")
82
- def init_auth(output, force):
83
- """Add auth.py with auth handler. Everything you need to start using the auth service."""
84
- root = get_git_root()
85
- if output and Path(output).is_file():
86
- click.secho("Output path is a file, please provide a directory path", fg="red")
87
- return
88
- target = (Path(output) if output else root) / "auth.py"
89
- if not check_file_exists(target, force):
90
- return
91
- copy_template("auth.py", target)
92
- click.secho(
93
- """
94
- Make sure to update the .env and .env.example files with:
95
- IS_DOCKER=0
96
- API_ENV=local
97
- and the docker-compose.yml file with:
98
- environment:
99
- - IS_DOCKER=1
100
- and the .github/workflows/main.yaml file with:
101
- env:
102
- API_ENV: ${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }}
103
- """,
104
- fg="yellow",
105
- )
106
-
107
-
108
- @init_group.command("dependabot")
109
- @click.option("-f", "--force", is_flag=True, help="Force overwrite the dependabot.yml")
110
- def init_dependabot(force):
111
- """Add dependabot.yml"""
112
- root = get_git_root()
113
- target = root / ".github/dependabot.yml"
114
- if not check_file_exists(target, force):
115
- return
116
- copy_template("dependabot.yml", target)
117
-
118
-
119
- @init_group.command("merge-env")
120
- @click.option("-f", "--force", is_flag=True, help="Force overwrite the .env file")
121
- def init_merge_env(force):
122
- """Add script to merge environment and file variables into .env"""
123
- root = get_git_root()
124
- target = root / "scripts/merge-env.sh"
125
- if not check_file_exists(target, force):
126
- return
127
- copy_template("merge-env.sh", target)
@@ -1,33 +0,0 @@
1
- from crypticorn.common import (
2
- AuthHandler as AuthHandler,
3
- Scope as Scope,
4
- Verify200Response as Verify200Response,
5
- BaseUrl as BaseUrl,
6
- ApiEnv as ApiEnv,
7
- )
8
- from fastapi import Security as Security
9
- import os
10
- import dotenv
11
- import logging
12
-
13
- dotenv.load_dotenv()
14
-
15
- logger = logging.getLogger(__name__)
16
-
17
- DOCKER_ENV = os.getenv("IS_DOCKER", "0")
18
- API_ENV = os.getenv("API_ENV")
19
-
20
- if not API_ENV:
21
- raise ValueError(
22
- "API_ENV is not set. Please set it to 'prod', 'dev' or 'local' in .env (of type ApiEnv)."
23
- )
24
-
25
- if DOCKER_ENV == "0":
26
- logger.info(f"Using {API_ENV} environment")
27
- base_url = BaseUrl.from_env(ApiEnv(API_ENV))
28
- else:
29
- base_url = BaseUrl.DOCKER
30
- logger.info("Using docker environment")
31
-
32
- auth_handler = AuthHandler(base_url=base_url)
33
- logger.info(f"Auth URL: {auth_handler.client.config.host}")
@@ -1,8 +0,0 @@
1
- import importlib.metadata
2
- import click
3
-
4
-
5
- @click.command("version")
6
- def version():
7
- """Print the version of the crypticorn package"""
8
- click.echo(importlib.metadata.distribution("crypticorn").version)
@@ -1,68 +0,0 @@
1
- import logging
2
- import warnings
3
- from enum import EnumMeta
4
-
5
- from crypticorn_utils.warnings import CrypticornDeprecatedSince28
6
-
7
- _logger = logging.getLogger("crypticorn")
8
-
9
-
10
- class ValidateEnumMixin:
11
- """
12
- Mixin for validating enum values manually.
13
-
14
- ⚠️ Note:
15
- This does NOT enforce validation automatically on enum creation.
16
- It's up to the developer to call `Class.validate(value)` where needed.
17
-
18
- Usage:
19
- >>> class Color(ValidateEnumMixin, StrEnum):
20
- >>> RED = "red"
21
- >>> GREEN = "green"
22
-
23
- >>> Color.validate("red") # True
24
- >>> Color.validate("yellow") # False
25
-
26
- Order of inheritance matters — the mixin must come first.
27
- """
28
-
29
- @classmethod
30
- def validate(cls, value) -> bool:
31
- """Validate if a value is in the enum. True if so, False otherwise."""
32
- try:
33
- cls(value)
34
- return True
35
- except ValueError:
36
- return False
37
-
38
-
39
- # This Mixin will be removed in a future version. And has no effect from now on
40
- class ExcludeEnumMixin:
41
- """(deprecated) Mixin to exclude enum from OpenAPI schema. We use this to avoid duplicating enums when generating client code from the openapi spec."""
42
-
43
- def __init_subclass__(cls, **kwargs):
44
- super().__init_subclass__(**kwargs)
45
- if cls.__name__.startswith("ExcludeEnumMixin"):
46
- warnings.warn(
47
- "The `ExcludeEnumMixin` class is deprecated. Should be removed from enums inheriting this class.",
48
- category=CrypticornDeprecatedSince28,
49
- )
50
-
51
- @classmethod
52
- def __get_pydantic_json_schema__(cls, core_schema, handler):
53
- schema = handler(core_schema)
54
- # schema.pop("enum", None)
55
- return schema
56
-
57
-
58
- class ApiErrorFallback(EnumMeta):
59
- """Fallback for enum members that are not yet published to PyPI."""
60
-
61
- def __getattr__(cls, name):
62
- # Let Pydantic/internal stuff pass silently ! fragile
63
- if name.startswith("__") or name.startswith("_pytest"):
64
- raise AttributeError(name)
65
- _logger.warning(
66
- f"Unknown enum member '{name}' - update crypticorn package or check for typos"
67
- )
68
- return cls.UNKNOWN_ERROR
@@ -1,10 +0,0 @@
1
- default_tags = [
2
- {
3
- "name": "Status",
4
- "description": "These endpoints contain status operations.",
5
- },
6
- {
7
- "name": "Admin",
8
- "description": "These endpoints contain debugging and monitoring operations. They require admin scopes.",
9
- },
10
- ]
@@ -1,117 +0,0 @@
1
- """
2
- This module contains the admin router for the API.
3
- It provides endpoints for monitoring the server and getting information about the environment.
4
- ONLY ALLOW ACCESS TO THIS ROUTER WITH ADMIN SCOPES.
5
- >>> app.include_router(admin_router, dependencies=[Security(auth_handler.full_auth, scopes=[Scope.READ_ADMIN, Scope.WRITE_ADMIN])])
6
- """
7
-
8
- import importlib.metadata
9
- import logging
10
- import os
11
- import re
12
- import threading
13
- import time
14
- from typing import Literal
15
-
16
- import psutil
17
- from crypticorn_utils.logging import LogLevel
18
- from crypticorn_utils.metrics import registry
19
- from fastapi import APIRouter, Query, Response
20
- from prometheus_client import CONTENT_TYPE_LATEST, generate_latest
21
-
22
- router = APIRouter(tags=["Admin"], prefix="/admin")
23
-
24
- START_TIME = time.time()
25
-
26
-
27
- @router.get("/log-level", status_code=200, operation_id="getLogLevel", deprecated=True)
28
- async def get_logging_level() -> LogLevel:
29
- """
30
- Get the log level of the server logger. Will be removed in a future release.
31
- """
32
- return LogLevel.get_name(logging.getLogger().level)
33
-
34
-
35
- @router.get("/uptime", operation_id="getUptime", status_code=200)
36
- def get_uptime(type: Literal["seconds", "human"] = "seconds") -> str:
37
- """Return the server uptime in seconds or human-readable form."""
38
- uptime_seconds = int(time.time() - START_TIME)
39
- if type == "seconds":
40
- return str(uptime_seconds)
41
- elif type == "human":
42
- return time.strftime("%H:%M:%S", time.gmtime(uptime_seconds))
43
-
44
-
45
- @router.get("/memory", operation_id="getMemoryUsage", status_code=200)
46
- def get_memory_usage() -> float:
47
- """
48
- Resident Set Size (RSS) in MB — the actual memory used by the process in RAM.
49
- Represents the physical memory footprint. Important for monitoring real usage.
50
- """
51
- process = psutil.Process(os.getpid())
52
- mem_info = process.memory_info()
53
- return round(mem_info.rss / (1024 * 1024), 2)
54
-
55
-
56
- @router.get("/threads", operation_id="getThreads", status_code=200)
57
- def get_threads() -> dict:
58
- """Return count and names of active threads."""
59
- threads = threading.enumerate()
60
- return {
61
- "count": len(threads),
62
- "threads": [t.name for t in threads],
63
- }
64
-
65
-
66
- @router.get("/limits", operation_id="getContainerLimits", status_code=200)
67
- def get_container_limits() -> dict:
68
- """Return container resource limits from cgroup."""
69
- limits = {}
70
- try:
71
- with open("/sys/fs/cgroup/memory/memory.limit_in_bytes") as f:
72
- limits["memory_limit_MB"] = int(f.read().strip()) / 1024 / 1024
73
- except Exception:
74
- limits["memory_limit_MB"] = "N/A"
75
-
76
- try:
77
- with open("/sys/fs/cgroup/cpu/cpu.cfs_quota_us") as f1, open(
78
- "/sys/fs/cgroup/cpu/cpu.cfs_period_us"
79
- ) as f2:
80
- quota = int(f1.read().strip())
81
- period = int(f2.read().strip())
82
- limits["cpu_limit_cores"] = quota / period if quota > 0 else "N/A"
83
- except Exception:
84
- limits["cpu_limit_cores"] = "N/A"
85
-
86
- return limits
87
-
88
-
89
- @router.get("/dependencies", operation_id="getDependencies", status_code=200)
90
- def list_installed_packages(
91
- include: list[str] = Query(
92
- default=None,
93
- description="List of regex patterns to match against package names. If not provided, all installed packages will be returned.",
94
- )
95
- ) -> dict[str, str]:
96
- """Return a list of installed packages and versions.
97
-
98
- The include parameter accepts regex patterns to match against package names.
99
- For example:
100
- - crypticorn.* will match all packages starting with 'crypticorn'
101
- - .*tic.* will match all packages containing 'tic' in their name
102
- """
103
- packages = {
104
- dist.metadata["Name"]: dist.version
105
- for dist in importlib.metadata.distributions()
106
- if include is None
107
- or any(re.match(pattern, dist.metadata["Name"]) for pattern in include)
108
- }
109
- return dict(sorted(packages.items()))
110
-
111
-
112
- @router.get("/metrics", operation_id="getMetrics")
113
- def metrics():
114
- """
115
- Get Prometheus metrics for the application. Returns plain text.
116
- """
117
- return Response(generate_latest(registry), media_type=CONTENT_TYPE_LATEST)
@@ -1,36 +0,0 @@
1
- """
2
- This module contains the status router for the API.
3
- It provides endpoints for checking the status of the API and get the server's time.
4
- SHOULD ALLOW ACCESS TO THIS ROUTER WITHOUT AUTH.
5
- To enable metrics, pass enable_metrics=True and the auth_handler to the router.
6
- >>> status_router.enable_metrics = True
7
- >>> status_router.auth_handler = auth_handler
8
- Then include the router in the FastAPI app.
9
- >>> app.include_router(status_router)
10
- """
11
-
12
- from datetime import datetime
13
- from typing import Literal
14
-
15
- from fastapi import APIRouter, Request
16
-
17
- router = APIRouter(tags=["Status"], prefix="")
18
-
19
-
20
- @router.get("/", operation_id="ping")
21
- async def ping(request: Request) -> str:
22
- """
23
- Returns 'OK' if the API is running.
24
- """
25
- return "OK"
26
-
27
-
28
- @router.get("/time", operation_id="getTime")
29
- async def time(type: Literal["iso", "unix"] = "iso") -> str:
30
- """
31
- Returns the current time in either ISO or Unix timestamp (seconds) format.
32
- """
33
- if type == "iso":
34
- return datetime.now().isoformat()
35
- elif type == "unix":
36
- return str(int(datetime.now().timestamp()))
@@ -1,30 +0,0 @@
1
- crypticorn_utils/__init__.py,sha256=PlxMppwUMmbNR9Jr1z9DNCYAYnTuWzW9IFyGTwV5slA,700
2
- crypticorn_utils/_migration.py,sha256=YPVEDVIz9Lt3ntwrVmUtavQxsJVjtSqQeQ0A_qydiaY,445
3
- crypticorn_utils/ansi_colors.py,sha256=-tMlUTE8NI7TPv7uj0kGRe-SI2hGaUNPKBFI_dfiZy0,1392
4
- crypticorn_utils/auth.py,sha256=oJORAuYBD0qiAmUpbMe0JSvp_gsof3oQMNpqay8L6Ek,13018
5
- crypticorn_utils/decorators.py,sha256=chsbF27_q3hC0egBaZLfv2vcqUcBSfQXRkLi3Ewb-20,1063
6
- crypticorn_utils/enums.py,sha256=hr6QfOwl8AnfPDtxBDc-v7TA9hzKkPhFq0ZdREb6Hzc,5059
7
- crypticorn_utils/errors.py,sha256=tR1yZCfI7DL0k7mKHfsRdWNMDU8hNB5v91YLShikWoY,30429
8
- crypticorn_utils/exceptions.py,sha256=iHJOtEBrqgzZVa3ZC60TVYpEfUnhxzos_A9QefmVXT8,6633
9
- crypticorn_utils/logging.py,sha256=510DSQr4g5UbweSvZAxjdUKtmj-LU3Dw0clARaAvsZA,4439
10
- crypticorn_utils/metrics.py,sha256=WjnNs3RE6A_LzO7m_2hp6EQHvOw1r_nWa2Okhm1OGB0,867
11
- crypticorn_utils/middleware.py,sha256=tr6IOti_xrZPA5EoFJpEFqLJ2VuxSnXHkCjsFLBtp6w,4130
12
- crypticorn_utils/mixins.py,sha256=bN55jStSXk9XGskChh1OE80Oj4B6Wg8LDpxFkP0vw5I,2206
13
- crypticorn_utils/openapi.py,sha256=D8bCpCVVzYQptHrJ7SYOgCxI3R_d0cjW9KMOBq-x0xk,279
14
- crypticorn_utils/pagination.py,sha256=06shym28tfD-Cc9EPk2W7K2GHqUj2Kk4ShQ0BrKCDWY,11432
15
- crypticorn_utils/utils.py,sha256=DXIOjJCdrDqoNCLAtohWYrFnEd1nvmg9NXdL07yWAgk,3137
16
- crypticorn_utils/warnings.py,sha256=ErEB108UVZgV5ykSuFkjQgDTb9sb_T9yKq-h753Kw64,3085
17
- crypticorn_utils/cli/__init__.py,sha256=5qIQ_WXKSoJk3tGU6n0XwmSX8a2cDRSM6dncaU1qOZ4,123
18
- crypticorn_utils/cli/__main__.py,sha256=q_3MdBGUJPukr_xexup3TICf8kLL7Tp4JxLWB5XCESs,303
19
- crypticorn_utils/cli/init.py,sha256=Ubu0eOwUqVweb4EzqsceV4K5VMN2qz6_Riy9h2Pjb64,4099
20
- crypticorn_utils/cli/version.py,sha256=OVDxeL80eMgZsFgw2cDSzFfuaRToDfnYAVOQTpkoMWs,206
21
- crypticorn_utils/cli/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
- crypticorn_utils/cli/templates/auth.py,sha256=i27-Ts-Eiyv6_WRshOp7NV5OYUNbw2-kiN5Ll0k2UOA,839
23
- crypticorn_utils/router/admin_router.py,sha256=B8s0hqOFe6CFTTsCxtwMUZSdb5EbRsFeKPixH9CXwOU,4090
24
- crypticorn_utils/router/status_router.py,sha256=tqrTXq4ZWCxiTXinQoK-2tadWu2jUFzzzkN_Dft0P8g,1084
25
- crypticorn_utils-0.1.0rc1.dist-info/licenses/LICENSE,sha256=HonAVvzFXkP2C1d7D3ByIKPwjGH8NcHTAQvKH7uvOHQ,1856
26
- crypticorn_utils-0.1.0rc1.dist-info/METADATA,sha256=HflK4V5Gk-AlTWBT5HtDTQLK3MWZBiPrrbk8gQZcoyk,3999
27
- crypticorn_utils-0.1.0rc1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
28
- crypticorn_utils-0.1.0rc1.dist-info/entry_points.txt,sha256=G4yWDll7v_Kb4uemqI-_qTKXHvs10R4mD7hNuD-biv4,71
29
- crypticorn_utils-0.1.0rc1.dist-info/top_level.txt,sha256=jLPvdxnI36RPf8TX3aZhl35OSd721xEYyFSEeQKF6Ic,17
30
- crypticorn_utils-0.1.0rc1.dist-info/RECORD,,