This commit is contained in:
2025-08-20 04:15:43 +02:00
parent 6b9f0cf291
commit e4bb201181
95 changed files with 194 additions and 907 deletions

View File

@@ -1,4 +1,57 @@
# herolib_python
see also ~/code/git.ourworld.tf/tfgrid_research/tfdev
has some usefull stuff as well
has some usefull stuff as well
## Installation
You can install `herolib` directly from the Git repository using `uv pip` (or `pip`):
```bash
uv pip install git+https://git.ourworld.tf/herocode/herolib_python.git
```
To install in editable mode for development:
```bash
uv pip install -e git+https://git.ourworld.tf/herocode/herolib_python.git#egg=herolib
```
## Usage
Once installed, you can import modules from the `herolib` package:
```python
import herolib.core.loghandler.mylogging
# Or import specific functions/classes
from herolib.core.loghandler.mylogging import MyLogger
```
## Version Control
This library follows standard Git version control practices. Releases can be managed by tagging specific commits in the Git repository. Users installing directly from the Git URL can specify a particular branch, tag, or commit hash to get a specific version. For example:
```bash
# Install from a specific branch
uv pip install git+https://git.ourworld.tf/herocode/herolib_python.git@main
# Install from a specific tag (e.g., v0.1.0)
uv pip install git+https://git.ourworld.tf/herocode/herolib_python.git@v0.1.0
# Install from a specific commit hash
uv pip install git+https://git.ourworld.tf/herocode/herolib_python.git@<commit_hash>
```
## Adding as a Dependency in `pyproject.toml`
To include `herolib` as a dependency in another Python project that uses `pyproject.toml`, you can add it to the `dependencies` section of your project's `pyproject.toml` file. This is particularly useful for development or when you need to pin to a specific version or branch.
Example `pyproject.toml` for another project:
```toml
[project]
name = "my-other-project"
version = "0.1.0"
dependencies = [
"herolib @ git+https://git.ourworld.tf/herocode/herolib_python.git",
]

View File

@@ -5,8 +5,62 @@ Summary: A Python library for HeroCode
Author-email: Kilo Code <kilo.code@example.com>
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: peewee
# herolib_python
see also ~/code/git.ourworld.tf/tfgrid_research/tfdev
has some usefull stuff as well
## Installation
You can install `herolib` directly from the Git repository using `uv pip` (or `pip`):
```bash
uv pip install git+https://git.ourworld.tf/herocode/herolib_python.git
```
To install in editable mode for development:
```bash
uv pip install -e git+https://git.ourworld.tf/herocode/herolib_python.git#egg=herolib
```
## Usage
Once installed, you can import modules from the `herolib` package:
```python
import herolib.core.loghandler.mylogging
# Or import specific functions/classes
from herolib.core.loghandler.mylogging import MyLogger
```
## Version Control
This library follows standard Git version control practices. Releases can be managed by tagging specific commits in the Git repository. Users installing directly from the Git URL can specify a particular branch, tag, or commit hash to get a specific version. For example:
```bash
# Install from a specific branch
uv pip install git+https://git.ourworld.tf/herocode/herolib_python.git@main
# Install from a specific tag (e.g., v0.1.0)
uv pip install git+https://git.ourworld.tf/herocode/herolib_python.git@v0.1.0
# Install from a specific commit hash
uv pip install git+https://git.ourworld.tf/herocode/herolib_python.git@<commit_hash>
```
## Adding as a Dependency in `pyproject.toml`
To include `herolib` as a dependency in another Python project that uses `pyproject.toml`, you can add it to the `dependencies` section of your project's `pyproject.toml` file. This is particularly useful for development or when you need to pin to a specific version or branch.
Example `pyproject.toml` for another project:
```toml
[project]
name = "my-other-project"
version = "0.1.0"
dependencies = [
"herolib @ git+https://git.ourworld.tf/herocode/herolib_python.git",
]

View File

@@ -1,78 +1,79 @@
README.md
pyproject.toml
herolib/__init__.py
herolib.egg-info/PKG-INFO
herolib.egg-info/SOURCES.txt
herolib.egg-info/dependency_links.txt
herolib.egg-info/requires.txt
herolib.egg-info/top_level.txt
lib/__init__.py
lib/clients/__init__.py
lib/clients/assemblyai/__init__.py
lib/clients/assemblyai/client.py
lib/clients/stellar/__init__.py
lib/clients/stellar/horizon.py
lib/clients/stellar/model.py
lib/clients/stellar/testnet.py
lib/clients/telegram/__init__.py
lib/clients/telegram/bot.py
lib/clients/telegram/bot_audio.py
lib/clients/telegram/bot_text.py
lib/clients/telegram/errorqueue.py
lib/clients/vimeo/__init__.py
lib/clients/vimeo/client.py
lib/clients/vimeo/model_video.py
lib/clients/whisper/__init__.py
lib/clients/whisper/convert.py
lib/clients/whisper/whisper.py
lib/clients/wireless/__init__.py
lib/clients/wireless/wigle_net.py
lib/core/__init__.py
lib/core/heroscript/__init__.py
lib/core/heroscript/heroaction.py
lib/core/heroscript/heroscripts.py
lib/core/heroscript/mixin.py
lib/core/heroscript/tools.py
lib/core/heroscript/examples/__init__.py
lib/core/heroscript/examples/heroscript_example.py
lib/core/heroscript/examples/heroscript_example2.py
lib/core/heroscript/examples/wiki/__init__.py
lib/core/heroscript/examples/wiki/sub/__init__.py
lib/core/logger/__init__.py
lib/core/logger/factory.py
lib/core/logger/log.py
lib/core/logger/log_test.py
lib/core/logger/model.py
lib/core/logger/search.py
lib/core/loghandler/__init__.py
lib/core/loghandler/mylogging.py
lib/core/pathlib/__init__.py
lib/core/pathlib/pathlib.py
lib/core/texttools/__init__.py
lib/core/texttools/texttools.py
lib/crypt/__init__.py
lib/crypt/box/__init__.py
lib/crypt/box/box.py
lib/crypt/box/box_api.py
lib/data/__init__.py
lib/data/ourtime/__init__.py
lib/data/ourtime/ourtime.py
lib/downloader/__init__.py
lib/downloader/scrape_dynamic/dynamic_crawl.py
lib/downloader/scrape_scapegraph/main.py
lib/downloader/scrape_scapegraph/scrape.py
lib/downloader/scrape_scapegraph/scrape_md.py
lib/downloader/scrape_scapegraph/scrape_search.py
lib/downloader/scrape_scapegraph/scrape_with_local_llm.py
lib/downloader/scrape_scapegraph/scrape_with_local_llm_search.py
lib/tools/__init__.py
lib/tools/extensions.py
lib/tools/gitscanner.py
lib/tools/logger.py
lib/tools/md5.py
lib/tools/ourtime.py
lib/tools/pathtools.py
lib/tools/texttools.py
lib/web/__init__.py
lib/web/doctools/__init__.py
lib/web/doctools/html_replacer.py
lib/web/doctools/md_replacer.py
lib/web/doctools/processor.py
herolib/clients/__init__.py
herolib/clients/assemblyai/__init__.py
herolib/clients/assemblyai/client.py
herolib/clients/stellar/__init__.py
herolib/clients/stellar/horizon.py
herolib/clients/stellar/model.py
herolib/clients/stellar/testnet.py
herolib/clients/telegram/__init__.py
herolib/clients/telegram/bot.py
herolib/clients/telegram/bot_audio.py
herolib/clients/telegram/bot_text.py
herolib/clients/telegram/errorqueue.py
herolib/clients/vimeo/__init__.py
herolib/clients/vimeo/client.py
herolib/clients/vimeo/model_video.py
herolib/clients/whisper/__init__.py
herolib/clients/whisper/convert.py
herolib/clients/whisper/whisper.py
herolib/clients/wireless/__init__.py
herolib/clients/wireless/wigle_net.py
herolib/core/__init__.py
herolib/core/heroscript/__init__.py
herolib/core/heroscript/heroaction.py
herolib/core/heroscript/heroscripts.py
herolib/core/heroscript/mixin.py
herolib/core/heroscript/tools.py
herolib/core/heroscript/examples/__init__.py
herolib/core/heroscript/examples/heroscript_example.py
herolib/core/heroscript/examples/heroscript_example2.py
herolib/core/heroscript/examples/wiki/__init__.py
herolib/core/heroscript/examples/wiki/sub/__init__.py
herolib/core/logger/__init__.py
herolib/core/logger/factory.py
herolib/core/logger/log.py
herolib/core/logger/log_test.py
herolib/core/logger/model.py
herolib/core/logger/search.py
herolib/core/loghandler/__init__.py
herolib/core/loghandler/mylogging.py
herolib/core/pathlib/__init__.py
herolib/core/pathlib/pathlib.py
herolib/core/texttools/__init__.py
herolib/core/texttools/texttools.py
herolib/crypt/__init__.py
herolib/crypt/box/__init__.py
herolib/crypt/box/box.py
herolib/crypt/box/box_api.py
herolib/data/__init__.py
herolib/data/ourtime/__init__.py
herolib/data/ourtime/ourtime.py
herolib/downloader/__init__.py
herolib/downloader/scrape_dynamic/dynamic_crawl.py
herolib/downloader/scrape_scapegraph/main.py
herolib/downloader/scrape_scapegraph/scrape.py
herolib/downloader/scrape_scapegraph/scrape_md.py
herolib/downloader/scrape_scapegraph/scrape_search.py
herolib/downloader/scrape_scapegraph/scrape_with_local_llm.py
herolib/downloader/scrape_scapegraph/scrape_with_local_llm_search.py
herolib/tools/__init__.py
herolib/tools/extensions.py
herolib/tools/gitscanner.py
herolib/tools/logger.py
herolib/tools/md5.py
herolib/tools/ourtime.py
herolib/tools/pathtools.py
herolib/tools/texttools.py
herolib/web/__init__.py
herolib/web/doctools/__init__.py
herolib/web/doctools/html_replacer.py
herolib/web/doctools/md_replacer.py
herolib/web/doctools/processor.py

View File

@@ -0,0 +1 @@
peewee

View File

@@ -1 +1 @@
lib
herolib

Binary file not shown.

Binary file not shown.

View File

@@ -1,5 +1,5 @@
from lib.core.pathlib.pathlib import get_dir
from lib.core.logger.model import Logger
from herolib.core.pathlib.pathlib import get_dir
from herolib.core.logger.model import Logger
def new(path: str) -> Logger:
p = get_dir(path=path, create=True)

View File

@@ -1,7 +1,7 @@
from enum import Enum
from typing import Optional
from lib.data.ourtime.ourtime import OurTime
from lib.core.pathlib.pathlib import Path
from herolib.data.ourtime.ourtime import OurTime
from herolib.core.pathlib.pathlib import Path
class LogType(Enum):
STDOUT = "stdout"
@@ -15,8 +15,8 @@ class LogItemArgs:
self.logtype = logtype
import os
from lib.core.texttools.texttools import name_fix, expand, dedent
from lib.data.ourtime.ourtime import OurTime, now as ourtime_now
from herolib.core.texttools.texttools import name_fix, expand, dedent
from herolib.data.ourtime.ourtime import OurTime, now as ourtime_now
class Logger:
def __init__(self, path: Path, lastlog_time: int = 0):

View File

@@ -1,8 +1,8 @@
import os
from typing import Optional, List
from lib.core.texttools.texttools import name_fix
from lib.data.ourtime.ourtime import OurTime, new as ourtime_new
from lib.core.logger.model import Logger, LogItem, LogType
from herolib.core.texttools.texttools import name_fix
from herolib.data.ourtime.ourtime import OurTime, new as ourtime_new
from herolib.core.logger.model import Logger, LogItem, LogType
class SearchArgs:
def __init__(self, timestamp_from: Optional[OurTime] = None,

View File

@@ -1,822 +0,0 @@
<file_map>
/Users/despiegk/code/github/freeflowuniverse/herolib
├── aiprompts
│ └── herolib_core
│ ├── core_ourtime.md
│ ├── core_paths.md
│ └── core_text.md
└── lib
└── core
└── logger
├── factory.v
├── log_test.v
├── log.v
├── model.v
├── readme.md
└── search.v
</file_map>
<file_contents>
File: /Users/despiegk/code/github/freeflowuniverse/herolib/lib/core/logger/factory.v
```v
module logger
import freeflowuniverse.herolib.core.pathlib
pub fn new(path string) !Logger {
mut p := pathlib.get_dir(path: path, create: true)!
return Logger{
path: p
lastlog_time: 0
}
}
```
File: /Users/despiegk/code/github/freeflowuniverse/herolib/lib/core/logger/log_test.v
```v
module logger
import os
import freeflowuniverse.herolib.data.ourtime
import freeflowuniverse.herolib.core.pathlib
fn testsuite_begin() {
if os.exists('/tmp/testlogs') {
os.rmdir_all('/tmp/testlogs')!
}
}
fn test_logger() {
mut logger := new('/tmp/testlogs')!
// Test stdout logging
logger.log(LogItemArgs{
cat: 'test-app'
log: 'This is a test message\nWith a second line\nAnd a third line'
logtype: .stdout
timestamp: ourtime.new('2022-12-05 20:14:35')!
})!
// Test error logging
logger.log(LogItemArgs{
cat: 'error-test'
log: 'This is an error\nWith details'
logtype: .error
timestamp: ourtime.new('2022-12-05 20:14:35')!
})!
logger.log(LogItemArgs{
cat: 'test-app'
log: 'This is a test message\nWith a second line\nAnd a third line'
logtype: .stdout
timestamp: ourtime.new('2022-12-05 20:14:36')!
})!
logger.log(LogItemArgs{
cat: 'error-test'
log: '
This is an error
With details
'
logtype: .error
timestamp: ourtime.new('2022-12-05 20:14:36')!
})!
logger.log(LogItemArgs{
cat: 'error-test'
log: '
aaa
bbb
'
logtype: .error
timestamp: ourtime.new('2022-12-05 22:14:36')!
})!
logger.log(LogItemArgs{
cat: 'error-test'
log: '
aaa2
bbb2
'
logtype: .error
timestamp: ourtime.new('2022-12-05 22:14:36')!
})!
// Verify log directory exists
assert os.exists('/tmp/testlogs'), 'Log directory should exist'
// Get log file
files := os.ls('/tmp/testlogs')!
assert files.len == 2
mut file := pathlib.get_file(
path: '/tmp/testlogs/${files[0]}'
create: false
)!
content := file.read()!.trim_space()
items_stdout := logger.search(
timestamp_from: ourtime.new('2022-11-1 20:14:35')!
timestamp_to: ourtime.new('2025-11-1 20:14:35')!
logtype: .stdout
)!
assert items_stdout.len == 2
items_error := logger.search(
timestamp_from: ourtime.new('2022-11-1 20:14:35')!
timestamp_to: ourtime.new('2025-11-1 20:14:35')!
logtype: .error
)!
assert items_error.len == 4
}
fn testsuite_end() {
// if os.exists('/tmp/testlogs') {
// os.rmdir_all('/tmp/testlogs')!
// }
}
```
File: /Users/despiegk/code/github/freeflowuniverse/herolib/lib/core/logger/log.v
```v
module logger
import os
import freeflowuniverse.herolib.core.texttools
import freeflowuniverse.herolib.data.ourtime
@[params]
pub struct LogItemArgs {
pub mut:
timestamp ?ourtime.OurTime
cat string
log string
logtype LogType
}
pub fn (mut l Logger) log(args_ LogItemArgs) ! {
mut args := args_
t := args.timestamp or {
t2 := ourtime.now()
t2
}
// Format category (max 10 chars, ascii only)
args.cat = texttools.name_fix(args.cat)
if args.cat.len > 10 {
return error('category cannot be longer than 10 chars')
}
args.cat = texttools.expand(args.cat, 10, ' ')
args.log = texttools.dedent(args.log).trim_space()
mut logfile_path := '${l.path.path}/${t.dayhour()}.log'
// Create log file if it doesn't exist
if !os.exists(logfile_path) {
os.write_file(logfile_path, '')!
l.lastlog_time = 0 // make sure we put time again
}
mut f := os.open_append(logfile_path)!
mut content := ''
// Add timestamp if we're in a new second
if t.unix() > l.lastlog_time {
content += '\n${t.time().format_ss()}\n'
l.lastlog_time = t.unix()
}
// Format log lines
error_prefix := if args.logtype == .error { 'E' } else { ' ' }
lines := args.log.split('\n')
for i, line in lines {
if i == 0 {
content += '${error_prefix} ${args.cat} - ${line}\n'
} else {
content += '${error_prefix} ${line}\n'
}
}
f.writeln(content.trim_space_right())!
f.close()
}
```
File: /Users/despiegk/code/github/freeflowuniverse/herolib/lib/core/logger/model.v
```v
module logger
import freeflowuniverse.herolib.data.ourtime
import freeflowuniverse.herolib.core.pathlib
@[heap]
pub struct Logger {
pub mut:
path pathlib.Path
lastlog_time i64 // to see in log format, every second we put a time down, we need to know if we are in a new second (logs can come in much faster)
}
pub struct LogItem {
pub mut:
timestamp ourtime.OurTime
cat string
log string
logtype LogType
}
pub enum LogType {
stdout
error
}
```
File: /Users/despiegk/code/github/freeflowuniverse/herolib/lib/core/logger/readme.md
```md
# Logger Module
A simple logging system that provides structured logging with search capabilities.
Logs are stored in hourly files with a consistent format that makes them both human-readable and machine-parseable.
## Features
- Structured logging with categories and error types
- Automatic timestamp management
- Multi-line message support
- Search functionality with filtering options
- Human-readable log format
## Usage
```v
import freeflowuniverse.herolib.core.logger
import freeflowuniverse.herolib.data.ourtime
// Create a new logger
mut l := logger.new(path: '/var/logs')!
// Log a message
l.log(
cat: 'system',
log: 'System started successfully',
logtype: .stdout
)!
// Log an error
l.log(
cat: 'system',
log: 'Failed to connect\nRetrying in 5 seconds...',
logtype: .error
)!
// Search logs
results := l.search(
timestamp_from: ourtime.now().warp("-24h"), // Last 24 hours
cat: 'system', // Filter by category
log: 'failed', // Search in message content
logtype: .error, // Only error messages
maxitems: 100 // Limit results
)!
```
## Log Format
Each log file is named using the format `YYYY-MM-DD-HH.log` and contains entries in the following format:
```
21:23:42
system - This is a normal log message
system - This is a multi-line message
second line with proper indentation
third line maintaining alignment
E error_cat - This is an error message
E second line of error
E third line of error
```
### Format Rules
- Time stamps (HH:MM:SS) are written once per second when the log time changes
- Categories are:
- Limited to 10 characters maximum
- Padded with spaces to exactly 10 characters
- Any `-` in category names are converted to `_`
- Each line starts with either:
- ` ` (space) for normal logs (LogType.stdout)
- `E` for error logs (LogType.error)
- Multi-line messages maintain consistent indentation (14 spaces after the prefix)
```
File: /Users/despiegk/code/github/freeflowuniverse/herolib/lib/core/logger/search.v
```v
module logger
import os
import freeflowuniverse.herolib.core.texttools
import freeflowuniverse.herolib.data.ourtime
@[params]
pub struct SearchArgs {
pub mut:
timestamp_from ?ourtime.OurTime
timestamp_to ?ourtime.OurTime
cat string // can be empty
log string // any content in here will be looked for
logtype LogType
maxitems int = 10000
}
pub fn (mut l Logger) search(args_ SearchArgs) ![]LogItem {
mut args := args_
// Format category (max 10 chars, ascii only)
args.cat = texttools.name_fix(args.cat)
if args.cat.len > 10 {
return error('category cannot be longer than 10 chars')
}
mut timestamp_from := args.timestamp_from or { ourtime.OurTime{} }
mut timestamp_to := args.timestamp_to or { ourtime.OurTime{} }
// Get time range
from_time := timestamp_from.unix()
to_time := timestamp_to.unix()
if from_time > to_time {
return error('from_time cannot be after to_time: ${from_time} < ${to_time}')
}
mut result := []LogItem{}
// Find log files in time range
mut files := os.ls(l.path.path)!
files.sort()
for file in files {
if !file.ends_with('.log') {
continue
}
// Parse dayhour from filename
dayhour := file[..file.len - 4] // remove .log
file_time := ourtime.new(dayhour)!
mut current_time := ourtime.OurTime{}
mut current_item := LogItem{}
mut collecting := false
// Skip if file is outside time range
if file_time.unix() < from_time || file_time.unix() > to_time {
continue
}
// Read and parse log file
content := os.read_file('${l.path.path}/${file}')!
lines := content.split('\n')
for line in lines {
if result.len >= args.maxitems {
return result
}
line_trim := line.trim_space()
if line_trim == '' {
continue
}
// Check if this is a timestamp line
if !(line.starts_with(' ') || line.starts_with('E')) {
current_time = ourtime.new(line_trim)!
if collecting {
process(mut result, current_item, current_time, args, from_time, to_time)!
}
collecting = false
continue
}
if collecting && line.len > 14 && line[13] == `-` {
process(mut result, current_item, current_time, args, from_time, to_time)!
collecting = false
}
// Parse log line
is_error := line.starts_with('E')
if !collecting {
// Start new item
current_item = LogItem{
timestamp: current_time
cat: line[2..12].trim_space()
log: line[15..].trim_space()
logtype: if is_error { .error } else { .stdout }
}
// println('new current item: ${current_item}')
collecting = true
} else {
// Continuation line
if line_trim.len < 16 {
current_item.log += '\n'
} else {
current_item.log += '\n' + line[15..]
}
}
}
// Add last item if collecting
if collecting {
process(mut result, current_item, current_time, args, from_time, to_time)!
}
}
return result
}
fn process(mut result []LogItem, current_item LogItem, current_time ourtime.OurTime, args SearchArgs, from_time i64, to_time i64) ! {
// Add previous item if it matches filters
log_epoch := current_item.timestamp.unix()
if log_epoch < from_time || log_epoch > to_time {
return
}
if (args.cat == '' || current_item.cat.trim_space() == args.cat)
&& (args.log == '' || current_item.log.contains(args.log))
&& args.logtype == current_item.logtype {
result << current_item
}
}
```
File: /Users/despiegk/code/github/freeflowuniverse/herolib/aiprompts/herolib_core/core_ourtime.md
```md
# OurTime Module
The `OurTime` module in V provides flexible time handling, supporting relative and absolute time formats, Unix timestamps, and formatting utilities.
## Key Features
- Create time objects from strings or current time
- Relative time expressions (e.g., `+1h`, `-2d`)
- Absolute time formats (e.g., `YYYY-MM-DD HH:mm:ss`)
- Unix timestamp conversion
- Time formatting and warping
## Basic Usage
```v
import freeflowuniverse.herolib.data.ourtime
// Current time
mut t := ourtime.now()
// From string
t2 := ourtime.new('2022-12-05 20:14:35')!
// Get formatted string
println(t2.str()) // e.g., 2022-12-05 20:14
// Get Unix timestamp
println(t2.unix()) // e.g., 1670271275
```
## Time Formats
### Relative Time
Use `s` (seconds), `h` (hours), `d` (days), `w` (weeks), `M` (months), `Q` (quarters), `Y` (years).
```v
// Create with relative time
mut t := ourtime.new('+1w +2d -4h')!
// Warp existing time
mut t2 := ourtime.now()
t2.warp('+1h')!
```
### Absolute Time
Supports `YYYY-MM-DD HH:mm:ss`, `YYYY-MM-DD HH:mm`, `YYYY-MM-DD HH`, `YYYY-MM-DD`, `DD-MM-YYYY`.
```v
t1 := ourtime.new('2022-12-05 20:14:35')!
t2 := ourtime.new('2022-12-05')! // Time defaults to 00:00:00
```
## Methods Overview
### Creation
```v
now_time := ourtime.now()
from_string := ourtime.new('2023-01-15')!
from_epoch := ourtime.new_from_epoch(1673788800)
```
### Formatting
```v
mut t := ourtime.now()
println(t.str()) // YYYY-MM-DD HH:mm
println(t.day()) // YYYY-MM-DD
println(t.key()) // YYYY_MM_DD_HH_mm_ss
println(t.md()) // Markdown format
```
### Operations
```v
mut t := ourtime.now()
t.warp('+1h')! // Move 1 hour forward
unix_ts := t.unix()
is_empty := t.empty()
```
## Error Handling
Time parsing methods return a `Result` type and should be handled with `!` or `or` blocks.
```v
t_valid := ourtime.new('2023-01-01')!
t_invalid := ourtime.new('bad-date') or {
println('Error: ${err}')
ourtime.now() // Fallback
}
```
File: /Users/despiegk/code/github/freeflowuniverse/herolib/aiprompts/herolib_core/core_paths.md
```md
# Pathlib Usage Guide
## Overview
The pathlib module provides a comprehensive interface for handling file system operations. Key features include:
- Robust path handling for files, directories, and symlinks
- Support for both absolute and relative paths
- Automatic home directory expansion (~)
- Recursive directory operations
- Path filtering and listing
- File and directory metadata access
## Basic Usage
### Importing pathlib
```v
import freeflowuniverse.herolib.core.pathlib
```
### Creating Path Objects
```v
// Create a Path object for a file
mut file_path := pathlib.get("path/to/file.txt")
// Create a Path object for a directory
mut dir_path := pathlib.get("path/to/directory")
```
### Basic Path Operations
```v
// Get absolute path
abs_path := file_path.absolute()
// Get real path (resolves symlinks)
real_path := file_path.realpath()
// Check if path exists
if file_path.exists() {
// Path exists
}
```
## Path Properties and Methods
### Path Types
```v
// Check if path is a file
if file_path.is_file() {
// Handle as file
}
// Check if path is a directory
if dir_path.is_dir() {
// Handle as directory
}
// Check if path is a symlink
if file_path.is_link() {
// Handle as symlink
}
```
### Path Normalization
```v
// Normalize path (remove extra slashes, resolve . and ..)
normalized_path := file_path.path_normalize()
// Get path directory
dir_path := file_path.path_dir()
// Get path name without extension
name_no_ext := file_path.name_no_ext()
```
## File and Directory Operations
### File Operations
```v
// Write to file
file_path.write("Content to write")!
// Read from file
content := file_path.read()!
// Delete file
file_path.delete()!
```
### Directory Operations
```v
// Create directory
mut dir := pathlib.get_dir(
path: "path/to/new/dir"
create: true
)!
// List directory contents
mut dir_list := dir.list()!
// Delete directory
dir.delete()!
```
### Symlink Operations
```v
// Create symlink
file_path.link("path/to/symlink", delete_exists: true)!
// Resolve symlink
real_path := file_path.realpath()
```
## Advanced Operations
### Path Copying
```v
// Copy file to destination
file_path.copy(dest: "path/to/destination")!
```
### Recursive Operations
```v
// List directory recursively
mut recursive_list := dir.list(recursive: true)!
// Delete directory recursively
dir.delete()!
```
### Path Filtering
```v
// List files matching pattern
mut filtered_list := dir.list(
regex: [r".*\.txt$"],
recursive: true
)!
```
## Best Practices
### Error Handling
```v
if file_path.exists() {
// Safe to operate
} else {
// Handle missing file
}
```
```
File: /Users/despiegk/code/github/freeflowuniverse/herolib/aiprompts/herolib_core/core_text.md
```md
# TextTools Module
The `texttools` module provides a comprehensive set of utilities for text manipulation and processing.
## Functions and Examples:
```v
import freeflowuniverse.herolib.core.texttools
assert hello_world == texttools.name_fix("Hello World!")
```
### Name/Path Processing
* `name_fix(name string) string`: Normalizes filenames and paths.
* `name_fix_keepspace(name string) !string`: Like name_fix but preserves spaces.
* `name_fix_no_ext(name_ string) string`: Removes file extension.
* `name_fix_snake_to_pascal(name string) string`: Converts snake_case to PascalCase.
```v
name := texttools.name_fix_snake_to_pascal("hello_world") // Result: "HelloWorld"
```
* `snake_case(name string) string`: Converts PascalCase to snake_case.
```v
name := texttools.snake_case("HelloWorld") // Result: "hello_world"
```
* `name_split(name string) !(string, string)`: Splits name into site and page components.
### Text Cleaning
* `name_clean(r string) string`: Normalizes names by removing special characters.
```v
name := texttools.name_clean("Hello@World!") // Result: "HelloWorld"
```
* `ascii_clean(r string) string`: Removes all non-ASCII characters.
* `remove_empty_lines(text string) string`: Removes empty lines from text.
```v
text := texttools.remove_empty_lines("line1\n\nline2\n\n\nline3") // Result: "line1\nline2\nline3"
```
* `remove_double_lines(text string) string`: Removes consecutive empty lines.
* `remove_empty_js_blocks(text string) string`: Removes empty code blocks (```...```).
### Command Line Parsing
* `cmd_line_args_parser(text string) ![]string`: Parses command line arguments with support for quotes and escaping.
```v
args := texttools.cmd_line_args_parser("'arg with spaces' --flag=value") // Result: ['arg with spaces', '--flag=value']
```
* `text_remove_quotes(text string) string`: Removes quoted sections from text.
* `check_exists_outside_quotes(text string, items []string) bool`: Checks if items exist in text outside of quotes.
### Text Expansion
* `expand(txt_ string, l int, expand_with string) string`: Expands text to a specified length with a given character.
### Indentation
* `indent(text string, prefix string) string`: Adds indentation prefix to each line.
```v
text := texttools.indent("line1\nline2", " ") // Result: " line1\n line2\n"
```
* `dedent(text string) string`: Removes common leading whitespace from every line.
```v
text := texttools.dedent(" line1\n line2") // Result: "line1\nline2"
```
### String Validation
* `is_int(text string) bool`: Checks if text contains only digits.
* `is_upper_text(text string) bool`: Checks if text contains only uppercase letters.
### Multiline Processing
* `multiline_to_single(text string) !string`: Converts multiline text to a single line with proper escaping.
### Text Splitting
* `split_smart(t string, delimiter_ string) []string`: Intelligent string splitting that respects quotes.
### Tokenization
* `tokenize(text_ string) TokenizerResult`: Tokenizes text into meaningful parts.
* `text_token_replace(text string, tofind string, replacewith string) !string`: Replaces tokens in text.
### Version Parsing
* `version(text_ string) int`: Converts version strings to comparable integers.
```v
ver := texttools.version("v0.4.36") // Result: 4036
ver = texttools.version("v1.4.36") // Result: 1004036
```
### Formatting
* `format_rfc1123(t time.Time) string`: Formats a time.Time object into RFC 1123 format.
### Array Operations
* `to_array(r string) []string`: Converts a comma or newline separated list to an array of strings.
```v
text := "item1,item2,item3"
array := texttools.to_array(text) // Result: ['item1', 'item2', 'item3']
```
* `to_array_int(r string) []int`: Converts a text list to an array of integers.
* `to_map(mapstring string, line string, delimiter_ string) map[string]string`: Intelligent mapping of a line to a map based on a template.
```v
r := texttools.to_map("name,-,-,-,-,pid,-,-,-,-,path",
"root 304 0.0 0.0 408185328 1360 ?? S 16Dec23 0:34.06 /usr/sbin/distnoted")
// Result: {'name': 'root', 'pid': '1360', 'path': '/usr/sbin/distnoted'}
```
```
</file_contents>
<user_instructions>
create a module in python in location lib/core/logger in herolib_python
which reimplements /Users/despiegk/code/github/freeflowuniverse/herolib/lib/core/logger
all features need to be reimplemented
write me an implementation plan for my coding agent
</user_instructions>

View File

@@ -7,7 +7,7 @@ authors = [
]
readme = "README.md"
requires-python = ">=3.8"
dependencies = []
dependencies = ["peewee"]
[build-system]
requires = ["setuptools>=61.0"]
@@ -15,4 +15,4 @@ build-backend = "setuptools.build_meta"
[tool.setuptools.packages.find]
where = ["."]
include = ["lib*"]
include = ["herolib*"]