Skip to content

Commit 4c00c16

Browse files
committed
Add debug level logging statements
Onboard pre-commit
1 parent ba49b99 commit 4c00c16

8 files changed

+138
-26
lines changed

.github/workflows/python-publish.yaml

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
name: pypi-publish
2+
3+
on:
4+
release:
5+
types: [ published ]
6+
workflow_dispatch:
7+
8+
jobs:
9+
pypi-publisher:
10+
runs-on: thevickypedia-lite
11+
steps:
12+
- uses: thevickypedia/pypi-publisher@v3
13+
env:
14+
token: ${{ secrets.PYPI_TOKEN }}

.pre-commit-config.yaml

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
fail_fast: true
2+
exclude: ^(notebooks/|scripts/|.github/|docs/)
3+
repos:
4+
- repo: https://github.com/pre-commit/pre-commit-hooks
5+
rev: v4.5.0
6+
hooks:
7+
- id: check-added-large-files
8+
- id: check-ast
9+
- id: check-byte-order-marker
10+
- id: check-builtin-literals
11+
- id: check-case-conflict
12+
- id: check-docstring-first
13+
- id: check-executables-have-shebangs
14+
- id: check-shebang-scripts-are-executable
15+
- id: check-merge-conflict
16+
- id: check-toml
17+
- id: check-vcs-permalinks
18+
- id: check-xml
19+
- id: check-yaml
20+
- id: debug-statements
21+
- id: detect-aws-credentials
22+
- id: detect-private-key
23+
- id: end-of-file-fixer
24+
- id: fix-byte-order-marker
25+
- id: mixed-line-ending
26+
- id: name-tests-test
27+
- id: requirements-txt-fixer
28+
- id: trailing-whitespace
29+
30+
- repo: https://github.com/psf/black
31+
rev: 22.3.0
32+
hooks:
33+
- id: black
34+
exclude: docs_gen/
35+
36+
- repo: https://github.com/PyCQA/flake8
37+
rev: 7.0.0
38+
hooks:
39+
- id: flake8
40+
additional_dependencies:
41+
- flake8-docstrings
42+
- flake8-sfs
43+
args: [ --max-line-length=120, --extend-ignore=SFS3 D107 SFS301 D100 D104 D401 SFS101 SFS201 D412 ]
44+
45+
- repo: https://github.com/PyCQA/isort
46+
rev: 5.13.2
47+
hooks:
48+
- id: isort
49+
args: [ --profile, black ]
50+
51+
- repo: local
52+
hooks:
53+
- id: pytest_docs
54+
name: run pytest and generate runbook
55+
entry: /bin/bash pre_commit.sh
56+
language: system
57+
pass_filenames: false
58+
always_run: true

git2s3/__init__.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
"""Placeholder for package"""
1+
"""Placeholder for packaging."""
2+
3+
version = "0.0.0-a"

git2s3/config.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@
22
import os
33
from datetime import datetime
44

5-
from git2s3.models import LogOptions
5+
from git2s3.models import LogOptions, EnvConfig
66

77

8-
def default_logger(log: LogOptions) -> logging.Logger:
8+
def default_logger(env: EnvConfig) -> logging.Logger:
99
"""Generates a default console logger.
1010
1111
Args:
12-
log: Log option chosen by the user.
12+
env: Environment configuration.
1313
1414
Returns:
1515
logging.Logger:
1616
Logger object.
1717
"""
18-
if log == LogOptions.file:
18+
if env.log == LogOptions.file:
1919
if not os.path.isdir("logs"):
2020
os.mkdir("logs")
2121
logfile: str = datetime.now().strftime(
@@ -25,7 +25,10 @@ def default_logger(log: LogOptions) -> logging.Logger:
2525
else:
2626
handler = logging.StreamHandler()
2727
logger = logging.getLogger(__name__)
28-
logger.setLevel(level=logging.INFO)
28+
if env.debug:
29+
logger.setLevel(level=logging.DEBUG)
30+
else:
31+
logger.setLevel(level=logging.INFO)
2932
handler.setFormatter(
3033
fmt=logging.Formatter(
3134
fmt="%(asctime)s - %(levelname)-8s - [%(funcName)s:%(lineno)d] - %(message)s"

git2s3/models.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
else:
1010
from enum import Enum
1111

12-
1312
class StrEnum(str, Enum):
1413
"""Override for python 3.10 due to lack of StrEnum."""
1514

@@ -54,9 +53,7 @@ def parse_clone_dir(cls, value: str) -> DirectoryPath:
5453
if os.path.isdir(os.path.dirname(value)):
5554
os.makedirs(value)
5655
return value
57-
raise ValueError(
58-
f"{value!r} is neither a valid path, nor a potential path"
59-
)
56+
raise ValueError(f"{value!r} is neither a valid path, nor a potential path")
6057

6158
class Config:
6259
"""Environment variables configuration."""

main.py

+17-14
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@
1313
class Git2S3:
1414
def __init__(self, **kwargs):
1515
self.env = models.EnvConfig(**kwargs)
16-
self.logger = kwargs.get("logger", config.default_logger(self.env.log))
16+
self.logger = kwargs.get("logger", config.default_logger(self.env))
1717
self.repo = git.Repo()
1818
self.session = requests.Session()
1919
self.session.headers = {
20-
'Accept': 'application/vnd.github+json',
21-
'Authorization': f'Bearer {self.env.git_token}',
22-
'X-GitHub-Api-Version': '2022-11-28',
23-
'Content-Type': 'application/x-www-form-urlencoded',
20+
"Accept": "application/vnd.github+json",
21+
"Authorization": f"Bearer {self.env.git_token}",
22+
"X-GitHub-Api-Version": "2022-11-28",
23+
"Content-Type": "application/x-www-form-urlencoded",
2424
}
2525

2626
def get_all_repos(self) -> Generator[Dict[str, str]]:
@@ -30,10 +30,9 @@ def get_all_repos(self) -> Generator[Dict[str, str]]:
3030
Generator[Dict[str, str]]:
3131
Yields a dictionary of each repo's information.
3232
"""
33-
# todo: Add debug level logging for each API call, along with number of repos fetched and in break statements
34-
# Add .pre-commit config and pyproject.toml
3533
idx = 1
3634
while True:
35+
self.logger.debug("Fetching repos from page %d", idx)
3736
try:
3837
response = self.session.get(
3938
url=f"{self.env.git_api_url}orgs/{self.env.git_owner}/repos?per_page=1&page={idx}"
@@ -42,9 +41,13 @@ def get_all_repos(self) -> Generator[Dict[str, str]]:
4241
break
4342
json_response = response.json()
4443
if json_response:
44+
self.logger.debug(
45+
"Repositories in page %d: %d", idx, len(json_response)
46+
)
4547
yield from json_response
4648
idx += 1
4749
else:
50+
self.logger.debug("No repos found in page: %d, ending loop.", idx)
4851
break
4952

5053
def worker(self, repo: Dict[str, str]):
@@ -53,15 +56,15 @@ def worker(self, repo: Dict[str, str]):
5356
Args:
5457
repo: Repository information as JSON payload.
5558
"""
56-
self.logger.info("Cloning %s", repo.get('name'))
57-
repo_dest = os.path.join(self.env.clone_dir, repo.get('name'))
59+
self.logger.info("Cloning %s", repo.get("name"))
60+
repo_dest = os.path.join(self.env.clone_dir, repo.get("name"))
5861
if not os.path.isdir(repo_dest):
5962
os.makedirs(repo_dest)
6063
try:
61-
self.repo.clone_from(repo.get('clone_url'), str(repo_dest))
64+
self.repo.clone_from(repo.get("clone_url"), str(repo_dest))
6265
except GitCommandError as error:
6366
msg = error.stderr or error.stdout or ""
64-
msg = msg.strip().replace('\n', '').replace("'", "").replace('"', '')
67+
msg = msg.strip().replace("\n", "").replace("'", "").replace('"', "")
6568
self.logger.error(msg)
6669
# Raise an exception to indicate that the thread failed
6770
raise Exception(msg)
@@ -76,15 +79,15 @@ def cloner(self):
7679
with ThreadPoolExecutor(max_workers=os.cpu_count()) as executor:
7780
for repo in self.get_all_repos():
7881
future = executor.submit(self.worker, repo)
79-
futures[future] = repo.get('name')
82+
futures[future] = repo.get("name")
8083
for future in as_completed(futures):
8184
if future.exception():
8285
self.logger.error(
8386
"Thread processing for '%s' received an exception: %s",
8487
futures[future],
85-
future.exception()
88+
future.exception(),
8689
)
8790

8891

89-
if __name__ == '__main__':
92+
if __name__ == "__main__":
9093
Git2S3().cloner()

pyproject.toml

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
[project]
2+
name = "git2s3"
3+
dynamic = ["version"]
4+
description = "Backup GitHub projects to AWS S3"
5+
readme = "README.md"
6+
authors = [{ name = "Vignesh Rao", email = "[email protected]" }]
7+
license = { file = "LICENSE" }
8+
classifiers = [
9+
"License :: OSI Approved :: MIT License",
10+
"Programming Language :: Python :: 3",
11+
"Development Status :: 2 - Pre-Alpha", # todo: change dev status to "Development Status :: 5 - Production/Stable"
12+
"Operating System :: MacOS :: MacOS X",
13+
"Operating System :: Microsoft :: Windows",
14+
"Operating System :: POSIX :: Linux",
15+
"Topic :: System :: Archiving :: Backup"
16+
]
17+
keywords = ["git2s3", "backup"]
18+
requires-python = ">=3.10"
19+
20+
[tool.setuptools]
21+
packages = ["git2s3"]
22+
23+
[tool.setuptools.dynamic]
24+
version = {attr = "git2s3.version"}
25+
26+
[build-system]
27+
requires = ["setuptools", "wheel"]
28+
build-backend = "setuptools.build_meta"
29+
30+
[project.urls]
31+
Homepage = "https://github.com/thevickypedia/git2s3"
32+
Docs = "https://thevickypedia.github.io/git2s3"
33+
Source = "https://github.com/thevickypedia/git2s3"
34+
"Bug Tracker" = "https://github.com/thevickypedia/git2s3/issues"
35+
"Release Notes" = "https://github.com/thevickypedia/git2s3/blob/main/release_notes.rst"

requirements.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
requests==2.32.3
1+
GitPython==3.1.43
22
pydantic==2.7.4
33
pydantic-settings==2.3.4
4-
GitPython==3.1.43
4+
requests==2.32.3

0 commit comments

Comments
 (0)