Skip to content

Commit a215e4b

Browse files
authored
Merge pull request #29 from Cyber-Syntax/dev
refactor: logging and project structure
2 parents 98b63f2 + 645d7e8 commit a215e4b

29 files changed

Lines changed: 1637 additions & 795 deletions
Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,41 @@
11
---
22
name: Bug report
33
about: Create a report to help us improve
4-
title: "bug: "
4+
title: "🐞 bug: "
55
labels: bug
66
assignees: ""
77
---
88

9-
**please complete the following information:**
9+
**Versions**
1010

11-
- OS: [e.g. iOS]
12-
- Version [e.g. 0.2.3-beta]
13-
- Python version [e.g 3.11]
11+
- AutoTarCompress version: <!-- e.g: 0.10.10-alpha -->
12+
- Python version: <!-- [e.g 3.12] -->
1413

1514
**Describe the bug**
16-
A clear and concise description of what the bug is.
1715

18-
**To Reproduce**
19-
Steps to reproduce the behavior:
16+
<!-- A clear and concise description of what the bug is. -->
2017

21-
1. python3 main.py
22-
2. select choice 3
23-
3. See choice 1... 2..., select 2
24-
4. See this error:
18+
**Console Output**
2519

26-
```python
20+
<!-- Place to output in the below in the quotes -->
21+
22+
```
2723
2824
```
2925

3026
**Expected behavior**
31-
A clear and concise description of what you expected to happen.
3227

33-
**Additional context**
34-
Add any other context about the problem here.
28+
<!-- A clear and concise description of what you expected to happen. -->
29+
30+
**LOG**
31+
32+
> Paste the log(`/home/<your_username>/.local/state/autotarcompress/autotarcompress.log`) here:
3533
3634
```
3735
36+
3837
```
38+
39+
**Additional context**
40+
41+
<!-- Add any other context about the problem here. -->
Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
---
22
name: Feature request
33
about: Suggest an idea for this project
4-
title: "feat: "
4+
title: "🚀 feat: "
55
labels: enhancement
66
assignees: ""
77
---
88

99
**Is your feature request related to a problem? Please describe.**
10-
A clear and concise description of what the problem is.
11-
Ex. I'm always frustrated when [...]
10+
11+
<!-- A clear and concise description of what the problem is. -->
12+
<!-- Ex. I'm always frustrated when [...] -->
1213

1314
**Describe the solution you'd like**
14-
A clear and concise description of what you want to happen.
15+
16+
<!-- Clear and concise description of the solution you'd like to implement -->
1517

1618
**Describe alternatives you've considered**
17-
A clear and concise description of any alternative solutions or features you've considered.
19+
20+
<!-- Clear and concise description of any alternative solutions or features you've considered. -->

.github/copilot-instructions.md

Lines changed: 128 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,128 @@
1-
# Python Coding Rules
2-
3-
- Always add comments.
4-
- Follow PEP 8 style guidelines for code formatting.
5-
- Use meaningful variable and function names in snake_case.
6-
- Use UPPER_CASE for constants.
7-
- Use CamelCase for class names.
8-
- Add docstrings to all functions, classes, and modules following the Google style guide.
9-
- Use type hints to indicate parameter and return types.
10-
- Use f-strings for string formatting instead of older methods.
11-
- Implement proper exception handling with specific exception types.
12-
- Use logging instead of print statements for recording key actions and errors.
13-
- Store configuration in separate files (e.g., YAML, JSON, or .env) rather than hardcoding in scripts.
14-
- Always check return values from functions that may fail.
15-
- Write descriptive error messages that help diagnose the problem.
16-
- Keep functions focused on a single responsibility.
17-
- Use proper scoping for variables (avoid globals).
1+
You are an expert in Python for backup management and security. You will help me write modern, secure and efficient Python code. Follow the guidelines below to ensure best practices in Python development. Use sequential thinking while solving problems.
2+
3+
## Project Structure
4+
5+
- Put code in `src/`.
6+
- Put tests in `tests/`.
7+
- Put docs in `docs/`.
8+
- Put configs in `config/`.
9+
- Use `__init__.py` files to define package boundaries.
10+
- Order imports: standard library, third-party, then local.
11+
- Use absolute imports over relative imports.
12+
13+
## Code Style
14+
15+
- Follow Single Responsibility Principle (SRP).
16+
- Prioritize code clarity over cleverness.
17+
- Use snake_case naming convention.
18+
- Keep functions under 50 lines.
19+
- Use f-strings for string formatting.
20+
- Use pathlib for all file path operations.
21+
- Replace magic numbers with named constants.
22+
- Use guard clauses to avoid nested conditionals.
23+
- Specify file encoding explicitly.
24+
- Use logging over print.
25+
- Avoid premature optimization.
26+
- Avoid circular imports and tightly coupled modules.
27+
## Typing & Documentation
28+
29+
- Add type hints to all functions.
30+
- Add return type annotations explicitly.
31+
- Write docstrings for public modules, classes, and functions.
32+
- Keep docstrings concise and under 100 characters per line.
33+
- Show usage examples in module docstrings.
34+
- Use Google-style docstrings.
35+
36+
## Comments
37+
38+
- Explain why code exists.
39+
- Clarify complex logic.
40+
- Don't comment on obvious code.
41+
42+
## Functions & Design
43+
44+
- One function one responsibility.
45+
- Validate parameters at function start.
46+
- Prefer pure functions; separate stateful logic.
47+
- Prefer immutable data structures.
48+
- Use context managers for resources.
49+
- Use contextvars for async state.
50+
- Leverage Python's built-in functions and standard library.
51+
- Use `match/case` for complex conditionals when appropriate.
52+
- Avoid singleton patterns for better testability.
53+
54+
## Classes & OOP
55+
56+
- Desing single-purpose classes and methods.
57+
- Prefer dataclasses for simple data containers.
58+
- Favor composition over inheritance.
59+
- Use `@property` instead of getters/setters.
60+
- Implement `__eq__` and `__hash__` when needed.
61+
- Use `__slots__` to save memory when many instances.
62+
- Avoid god objects.
63+
64+
65+
66+
## Error Handling
67+
68+
- Handle errors and edge cases at the beginning of functions.
69+
- Use early returns for error conditions to avoid deeply nested if statements.
70+
- Create custom exception classes.
71+
- Catch specific exception types.
72+
- Preserve error context with `raise...from`.
73+
- Log exceptions with tracebacks.
74+
- Log with `logging.exception()` without secrets.
75+
- Redact secrets from logs and prints.
76+
- Validate inputs at system boundaries.
77+
- Keep try blocks minimal.
78+
- Use `with` or `finally` for cleanup.
79+
- Check return values from functions that might fail.
80+
- Use structured logging for traces.
81+
- Use assertions to check assumptions.
82+
83+
## Security
84+
85+
- Validate and sanitize all external inputs.
86+
- Use parameterized database queries.
87+
- Validate file paths and names.
88+
- Prevent directory traversal by validating paths.
89+
- Avoid eval() with untrusted input.
90+
- Load secrets from environment variables.
91+
- Use bcrypt/Argon2 for password hashing.
92+
- Generate unique salts per password.
93+
- Use HTTPS for network communication.
94+
- Make sure secrets aren't printed or logged.
95+
- Secrets should be stored in a secure vault or service.
96+
97+
## Performance
98+
99+
- Use asyncio for I/O tasks.
100+
- Profile code before optimizing.
101+
- Choose appropriate data structures.
102+
- Use generators for large datasets.
103+
- Cache pure functions with `@lru_cache`.
104+
- Avoid globals in hot paths.
105+
- Limit threads for CPU tasks.
106+
- Set timeouts on all blocking calls.
107+
- Use `''.join()` for many strings.
108+
- Consider JIT or Cython only for real bottlenecks.
109+
110+
## API Development
111+
112+
- Use `Bearer` for token auth.
113+
- Validate request data rigorously.
114+
- Validate inputs with Pydantic.
115+
- Implement rate limiting.
116+
- Implement OAuth2 or token-based auth.
117+
- Return consistent error responses.
118+
119+
## Testing Guidelines
120+
121+
- Use pytest for all tests with fixtures.
122+
- Mock external services in tests.
123+
- Test error paths explicitly.
124+
- Use Hypothesis for property testing.
125+
- Run static type checks in CI.
126+
- Focus on important behaviors, not coverage.
127+
- Use dependency injection for testability.
128+
- All tests should have typing annotations and docstrings

.github/workflows/main.yml

Lines changed: 99 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ jobs:
1515
steps:
1616
- name: Checkout code
1717
uses: actions/checkout@v4
18+
with:
19+
fetch-depth: 0 # Fetch all history to get commit messages
1820

1921
- name: Extract latest version and notes
2022
id: changelog
@@ -32,15 +34,111 @@ jobs:
3234
END { print notes; }
3335
' CHANGELOG.md)
3436
37+
# Get recent commits since last tag with GitHub usernames
38+
PREVIOUS_TAG=$(git describe --tags --abbrev=0 --match "v*" 2>/dev/null || echo "")
39+
40+
# Function to get GitHub username from email
41+
get_github_username() {
42+
local email="$1"
43+
local commit_hash="$2"
44+
45+
# First try to extract username from GitHub noreply email
46+
if [[ "$email" =~ ([0-9]+\+)?([^@]+)@users\.noreply\.github\.com ]]; then
47+
echo "${BASH_REMATCH[2]}"
48+
return
49+
fi
50+
51+
# Try to get GitHub username via API using commit hash
52+
local github_user=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
53+
"https://api.github.com/repos/$GITHUB_REPOSITORY/commits/$commit_hash" | \
54+
jq -r '.author.login // empty' 2>/dev/null)
55+
56+
if [ -n "$github_user" ] && [ "$github_user" != "null" ]; then
57+
echo "$github_user"
58+
return
59+
fi
60+
61+
# Fallback: try to get user by email via API
62+
local api_user=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
63+
"https://api.github.com/search/users?q=$email+in:email" | \
64+
jq -r '.items[0].login // empty' 2>/dev/null)
65+
66+
if [ -n "$api_user" ] && [ "$api_user" != "null" ]; then
67+
echo "$api_user"
68+
else
69+
# Final fallback: use the part before @ in email
70+
echo "${email%%@*}"
71+
fi
72+
}
73+
74+
# Get ALL conventional commits, excluding merge commits to avoid duplicates
75+
if [ -z "$PREVIOUS_TAG" ]; then
76+
COMMIT_DATA=$(git log --pretty=format:"%H|%ae|%s" --no-merges --grep="^\(feat\|fix\|docs\|style\|refactor\|perf\|test\|build\|ci\|chore\|revert\)")
77+
else
78+
COMMIT_DATA=$(git log ${PREVIOUS_TAG}..HEAD --pretty=format:"%H|%ae|%s" --no-merges --grep="^\(feat\|fix\|docs\|style\|refactor\|perf\|test\|build\|ci\|chore\|revert\)")
79+
fi
80+
81+
# Initialize categorized commit arrays
82+
FEATURES=""
83+
BUGFIXES=""
84+
OTHER_COMMITS=""
85+
86+
# Process ALL matching commits and categorize them
87+
while IFS='|' read -r hash email subject; do
88+
[ -z "$hash" ] && continue
89+
90+
# Get full commit message for PR detection
91+
message=$(git show -s --format=%B $hash)
92+
93+
# Extract username
94+
username=$(get_github_username "$email" "$hash")
95+
96+
# Check for ANY PR reference (#number)
97+
if [[ "$message" =~ \#([0-9]+) ]]; then
98+
pr_num=" (#${BASH_REMATCH[1]})"
99+
else
100+
pr_num=""
101+
fi
102+
103+
# Categorize based on conventional commit type
104+
if [[ "$subject" =~ ^feat(\(.+\))?:* ]]; then
105+
FEATURES="${FEATURES} - ${subject}${pr_num} (@$username)\n"
106+
elif [[ "$subject" =~ ^fix(\(.+\))?:* ]]; then
107+
BUGFIXES="${BUGFIXES} - ${subject}${pr_num} (@$username)\n"
108+
else
109+
OTHER_COMMITS="${OTHER_COMMITS} - ${subject}${pr_num} (@$username)\n"
110+
fi
111+
done <<< "$COMMIT_DATA"
112+
113+
# Build categorized commits section
114+
COMMITS=""
115+
if [ -n "$FEATURES" ]; then
116+
COMMITS="${COMMITS}#### 🚀 Features\n${FEATURES}\n"
117+
fi
118+
if [ -n "$BUGFIXES" ]; then
119+
COMMITS="${COMMITS}#### 🐛 Bug Fixes\n${BUGFIXES}\n"
120+
fi
121+
if [ -n "$OTHER_COMMITS" ]; then
122+
COMMITS="${COMMITS}#### 📝 Other Commits\n${OTHER_COMMITS}\n"
123+
fi
124+
125+
# Combine CHANGELOG notes with categorized commit messages
126+
if [ -n "$COMMITS" ]; then
127+
FULL_NOTES="${NOTES}\n\n### Commits\n${COMMITS}"
128+
else
129+
FULL_NOTES="${NOTES}"
130+
fi
131+
35132
# Save notes to output with correct GitHub multiline syntax
36133
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
37134
echo "notes<<$EOF" >> $GITHUB_OUTPUT
38-
echo "$NOTES" >> $GITHUB_OUTPUT
135+
echo -e "$FULL_NOTES" >> $GITHUB_OUTPUT
39136
echo "$EOF" >> $GITHUB_OUTPUT
40137
41138
# For debugging
42139
echo "Found version: $VERSION"
43140
echo "Release notes excerpt: $(echo "$NOTES" | head -3)..."
141+
echo "Commit messages excerpt: $(echo "$COMMITS" | head -3)..."
44142
45143
- name: Check for existing release
46144
id: check_release
@@ -56,10 +154,6 @@ jobs:
56154
env:
57155
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
58156

59-
- name: Create zip archive
60-
if: steps.check_release.outputs.exists == 'false'
61-
run: zip -r AutoTarCompress-${{ steps.changelog.outputs.version }}.zip ./ -x "*.git*" ".github/*"
62-
63157
- name: Create GitHub Release
64158
if: steps.check_release.outputs.exists == 'false'
65159
uses: softprops/action-gh-release@v1
@@ -69,6 +163,5 @@ jobs:
69163
body: ${{ steps.changelog.outputs.notes }}
70164
draft: false
71165
prerelease: ${{ contains(steps.changelog.outputs.version, '-') }}
72-
files: AutoTarCompress-${{ steps.changelog.outputs.version }}.zip
73166
env:
74167
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.gitignore

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,6 @@ dmypy.json
129129
# Pyre type checker
130130
.pyre/
131131

132-
# test
133-
*test*
134-
135132
# vscode
136133
.vscode/
137134

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Changelog
2-
All notable changes to this project will be documented in this file.
2+
All notable changes to this project will be documented in this file. Commits automatically generated by github actions.
3+
4+
## v0.4.0-beta
35

46
## v0.3.1-beta
57
### Changes

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
- You have two options:
5959
1. **Use an example config file (Recommended)**:
6060
- Copy the example configuration from `config_files_example/config.json`
61-
- Paste it into your `~/Documents/project_configs/AutoTarCompress/config_files/config.json` location
61+
- Paste it into your `~/.config/autotarcompress/config.json` location
6262
- Modify it as needed
6363
2. **Run the script and follow the on-screen instructions**.
6464
- This will guide you through creating a `config.json` file.

__init__.py

Whitespace-only changes.
File renamed without changes.

0 commit comments

Comments
 (0)