🚨 Latest Research:Tanstack npm Packages Compromised in Ongoing Mini Shai-Hulud Supply-Chain Attack.Learn More
Socket
Book a DemoSign in
Socket

libdev

Package Overview
Dependencies
Maintainers
1
Versions
102
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

libdev - pypi Package Compare versions

Comparing version
0.95
to
0.96
+1
-1
libdev.egg-info/PKG-INFO
Metadata-Version: 2.1
Name: libdev
Version: 0.95
Version: 0.96
Summary: Set of standard functions for development

@@ -5,0 +5,0 @@ Home-page: https://github.com/chilleco/lib

@@ -5,4 +5,4 @@ """

__version__ = "0.95"
__version__ = "0.96"
__all__ = ("__version__",)

@@ -0,4 +1,9 @@

"""Centralized configuration loader for LibDev consumers.
This module mirrors the behavior documented in `LIBDEV_DOCUMENTATION.md`:
it first ingests a project level ``sets.json`` file, then overlays values
from ``.env`` (via ``python-dotenv``) by translating dotted keys to
``UPPER_SNAKE_CASE`` environment variables. Use the helpers below instead of
calling ``os.getenv`` throughout the codebase so the hierarchy stays uniform.
"""
Functionality of getting configuration
"""

@@ -22,4 +27,12 @@ import os

def cfg(name, default=None):
"""Get config value by key"""
"""Return a config value stored in ``sets.json``/``.env``.
The lookup walks dotted paths inside the parsed JSON structure and, when a
key is missing, falls back to an environment variable where dots are
replaced with underscores and the string is upper-cased (``api.base`` →
``API_BASE``). Environment values are JSON-decoded automatically so booleans
and numeric strings turn into native Python types. ``default`` is returned
when a key is absent in both sources.
"""
keys = name.split(".")

@@ -48,4 +61,10 @@ data = sets

def set_cfg(name, value):
"""Set config value"""
"""Mutate the in-memory ``sets`` dictionary for tests or overrides.
Writes scoped dotted keys back into the ``sets`` mapping without touching
disk. This mirrors the behavior in consumer repos that temporarily adjust
configuration for integration tests or AI agents. Changes live only for the
current process and should be reset between tests.
"""
array_name = name.split(".")

@@ -52,0 +71,0 @@ dictionary = {}

@@ -242,2 +242,3 @@ """

def clear_text(data, extra=".,"):
"""Strip all characters except alphanumerics, space, and ``extra`` chars."""
return re.sub(rf"[^\w {extra}]", "", data).strip()

@@ -0,4 +1,7 @@

"""Development-environment helpers tied to LibDev guidelines.
Currently exposes public IP validation logic that mirrors the rules documented
in ``LIBDEV_DOCUMENTATION.md`` for analytics and logging pipelines. Extend this
module instead of sprinkling regex checks throughout consumer projects.
"""
Development tools
"""

@@ -9,4 +12,9 @@ import re

def check_public_ip(ip):
"""Check if the IP address is public"""
"""Return ``ip`` if it is routable on the public internet.
Private (RFC1918), loopback, and carrier-grade NAT subnets are filtered
out, ensuring only analyzable public addresses pass downstream. ``None`` is
returned for empty inputs or addresses that match reserved ranges.
"""
if not ip:

@@ -13,0 +21,0 @@ return None

@@ -0,4 +1,7 @@

"""Utility helpers for dealing with document/JSON serialization.
These functions are referenced by the integration guide to make sure assets
and structured logs look the same across repositories (e.g., ``log.json`` uses
``to_json`` under the hood).
"""
Documents processing functionality
"""

@@ -10,3 +13,8 @@ import base64

def to_base64(image, mime="image/jpg"):
"""Convert image to base64"""
"""Return a ``data:`` URL for the given file-like ``image``.
Reads the stream, base64-encodes the bytes, and prefixes it with the MIME
Type so downstream clients (frontends, bots) can embed the payload directly
without touching disk.
"""
data = base64.b64encode(image.read())

@@ -17,3 +25,7 @@ return f"data:{mime};base64,{data.decode('utf-8')}"

def to_json(data):
"""Convert object to json"""
"""Serialize ``data`` to a UTF-8 friendly JSON string.
Uses tab indentation and ``ensure_ascii=False`` to preserve Cyrillic or
emoji content mentioned in ``LIBDEV_DOCUMENTATION.md``.
"""
return json.dumps(data, indent="\t", ensure_ascii=False)

@@ -0,4 +1,7 @@

"""Numeric normalization and presentation helpers used across LibDev.
Implements the opinionated formatting rules discussed in the integration
guide: deterministic rounding, removal of floating-point artifacts, thousands
separators, and zero-compression for compact analytical displays.
"""
Numbers functionality
"""

@@ -25,3 +28,3 @@ import re

def to_num(value) -> bool:
"""Convert value to int or float"""
"""Convert an incoming scalar to ``int``/``float`` while preserving intent."""

@@ -84,4 +87,8 @@ if value is None:

def simplify_value(value, decimals=4):
"""Get the significant part of a number"""
"""Return the significant digits of ``value`` capped by ``decimals``.
Used by analytics pipelines to produce short strings that still encode the
important portion of very large or tiny numbers.
"""
if value is None:

@@ -131,4 +138,10 @@ return None

):
"""Decorate the number beautifully"""
"""Format ``value`` according to LibDev UI/metrics rules.
Supports optional rounding to a target precision, manual sign prefixing,
swapping the thousands separator symbol, and compressing leading/trailing
zeros (see ``compress_zeros``). This helper is the canonical way to build
user-facing number strings.
"""
if value is None:

@@ -288,2 +301,4 @@ return None

def to_plain(value) -> str:
"""Convert ``value`` to a normalized decimal string without notation."""
if value is None:

@@ -318,8 +333,14 @@ return None

def compress_zeros(x, zeros=2, round=None) -> str:
"""Compress zero runs using the subscript notation referenced in the docs.
Examples::
0.000012 -> "0.0₄12"
1.000045 -> "1.0₄45"
``round`` controls how many digits remain after the compressed block, while
``zeros`` sets the minimum run length required before a compression occurs.
Returns a string that can be passed to ``pretty`` or directly displayed in
dashboards.
"""
0.000012 -> '0.0₄12'
1.000045 -> '1.0₄45'
round: number of digits after the zero block (rounds).
zeros: minimum count of consecutive zeros to compress (default: 2).
"""

@@ -326,0 +347,0 @@ if x is None:

@@ -0,4 +1,8 @@

"""Async HTTP gateway used across LibDev powered projects.
Centralizes ``aiohttp`` usage so upstream services benefit from the same request
construction (JSON vs form payloads, multipart file uploads) and response
parsing rules described in ``LIBDEV_DOCUMENTATION.md``. Always ``await`` the
helpers in this module to stay inside the async boundary.
"""
Provides an asynchronous function to fetch data from a URL using aiohttp
"""

@@ -17,20 +21,11 @@ import aiohttp

):
"""
Fetch data from a URL using aiohttp.
"""Perform an HTTP request and normalize the response payload.
Args:
url (str): The URL to fetch data from.
payload (dict, optional): The payload to send with the request.
Defaults to None.
type_req (str, optional): The type of request (e.g., 'post', 'put',
'delete', etc.). Defaults to 'post'.
type_data (str, optional): The type of data (e.g., 'json', 'data').
Defaults to 'json'.
headers (dict, optional): The headers to include with the request.
Defaults to None.
timeout (float, optional): The timeout for the request in seconds.
Defaults to None.
Returns:
tuple: A tuple containing the status code and the response data.
Parameters mirror the rules from the integration guide: ``files`` may be a
mapping of field name to bytes/file-like objects (forcing multipart form
uploads), ``type_data`` controls whether the ``payload`` is supplied via the
``json`` or ``data`` keyword, and ``type_req`` is the lowercase HTTP verb. A
status code integer and the decoded response body (JSON dict, plain text, or
raw bytes) are returned. Callers are expected to provide their own retries
or circuit breaking logic.
"""

@@ -37,0 +32,0 @@ if payload is None:

@@ -0,4 +1,7 @@

"""Datetime parsing/formatting helpers aligned with LibDev localization rules.
The functions below implement the Russian month parsing, timezone handling, and
delta formatting conventions cited in ``LIBDEV_DOCUMENTATION.md`` so every
project surfaces dates the same way.
"""
Time functionality
"""

@@ -54,3 +57,3 @@ # TODO: Учитывать летнее / зимнее время в прошлых датах, которого теперь нет

def get_time(data=None, template="%d.%m.%Y %H:%M:%S", tz=0):
def get_time(data=None, template="%d.%m.%Y %H:%M:%S", tz=None):
"""Get time from timestamp"""

@@ -62,2 +65,4 @@

return data
if tz is None:
tz = 0

@@ -72,3 +77,3 @@ # TODO: smart TZ

def get_date(data=None, template="%d.%m.%Y", tz=0):
def get_date(data=None, template="%d.%m.%Y", tz=None):
"""Get date from timestamp"""

@@ -78,3 +83,3 @@ return get_time(data, template, tz)

def decode_time(data=None, template="%d.%m.%Y %H:%M:%S", tz=0):
def decode_time(data=None, template="%d.%m.%Y %H:%M:%S", tz=None):
"""Get timestamp from time"""

@@ -86,2 +91,4 @@

return data
if tz is None:
tz = 0

@@ -98,3 +105,3 @@ try:

def decode_date(data=None, template="%d.%m.%Y", tz=0):
def decode_date(data=None, template="%d.%m.%Y", tz=None):
"""Get timestamp from date"""

@@ -105,3 +112,3 @@ return decode_time(data, template, tz)

# pylint: disable=too-many-branches,too-many-statements
def parse_time(data: str, tz=0):
def parse_time(data: str, tz=None):
"""Parse time"""

@@ -111,2 +118,5 @@

if tz is None:
tz = 0
data = data.lower()

@@ -275,3 +285,3 @@

def get_midnight(timestamp=None, tz=0):
def get_midnight(timestamp=None, tz=None):
"""

@@ -287,10 +297,15 @@ Get the start of the day (midnight) for a given timestamp in a specified timezone.

"""
if timestamp is None:
timestamp = time.time()
if tz is None:
tz = 0
dt_local = datetime.datetime.fromtimestamp(timestamp, tz=to_tz(tz))
start_day = dt_local.replace(hour=0, minute=0, second=0, microsecond=0)
return int(start_day.timestamp())
def get_month_start(timestamp=None, tz=0):
def get_month_start(timestamp=None, tz=None):
"""

@@ -306,10 +321,21 @@ Get the start of the month (midnight on the first day of the month) for a given timestamp in a specified timezone.

"""
if timestamp is None:
timestamp = time.time()
if tz is None:
tz = 0
dt_local = datetime.datetime.fromtimestamp(timestamp, tz=to_tz(tz))
start_month = dt_local.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
return int(start_month.timestamp())
def get_week_start(timestamp=None, tz=0):
def get_previous_month(timestamp=None, tz=None):
current_period = get_month_start(timestamp, tz)
one_month_ago = get_month_start(current_period - 1, tz)
return one_month_ago
def get_week_start(timestamp=None, tz=None):
"""

@@ -325,13 +351,19 @@ Get the start of the week (midnight on Monday) for a given timestamp in a specified timezone.

"""
if timestamp is None:
timestamp = time.time()
if tz is None:
tz = 0
dt_local = datetime.datetime.fromtimestamp(timestamp, tz=to_tz(tz))
# Calculate days to subtract to get to Monday (weekday() returns 0 for Monday, 6 for Sunday)
days_since_monday = dt_local.weekday()
start_week = dt_local - datetime.timedelta(days=days_since_monday)
start_week = start_week.replace(hour=0, minute=0, second=0, microsecond=0)
return int(start_week.timestamp())
def get_next_day(timestamp=None, tz=0):
def get_next_day(timestamp=None, tz=None):
"""

@@ -347,4 +379,8 @@ Get the start of the next day (midnight) for a given timestamp in a specified timezone.

"""
if timestamp is None:
timestamp = time.time()
if tz is None:
tz = 0
dt_local = datetime.datetime.fromtimestamp(timestamp, tz=to_tz(tz))

@@ -354,2 +390,3 @@ next_day = (dt_local + datetime.timedelta(days=1)).replace(

)
return int(next_day.timestamp())

@@ -359,3 +396,3 @@

# TODO: get previous month (params=-1 +1)
def get_next_month(timestamp=None, tz=0):
def get_next_month(timestamp=None, tz=None):
"""

@@ -374,2 +411,4 @@ Get the start of the next month (midnight on the first day of the next month) for a given timestamp in a specified timezone.

timestamp = time.time()
if tz is None:
tz = 0

@@ -376,0 +415,0 @@ dt_local = datetime.datetime.fromtimestamp(timestamp, tz=to_tz(tz))

Metadata-Version: 2.1
Name: libdev
Version: 0.95
Version: 0.96
Summary: Set of standard functions for development

@@ -5,0 +5,0 @@ Home-page: https://github.com/chilleco/lib

@@ -160,2 +160,3 @@ from libdev.num import (

assert pretty(12345.6, 3, True) == "+12’346"
assert pretty(1046012.4859999998, 0) == "1’046’012"
assert pretty(-0.000000235235, zeros=None, compress=None) == "-0.000000235235"

@@ -162,0 +163,0 @@ assert pretty(-0.000000235235, zeros=4, compress=2) == "-0.0₆24"

@@ -16,2 +16,3 @@ """

get_month_start,
get_previous_month,
get_next_day,

@@ -125,2 +126,8 @@ get_next_month,

def test_get_previous_month():
assert get_previous_month() == 1759276800
assert get_previous_month(tz=3) == 1759266000
assert get_previous_month(1760648400, 1) == 1756681200
def test_get_next_day():

@@ -127,0 +134,0 @@ assert get_next_day(1704060061) == 1704067200