snakemake-logger-plugin-rich 0.1.0__tar.gz

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.
@@ -0,0 +1,137 @@
1
+ name: release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "[0-9]+.[0-9]+.[0-9]+"
7
+ - "[0-9]+.[0-9]+.[0-9]+a[0-9]+"
8
+ - "[0-9]+.[0-9]+.[0-9]+b[0-9]+"
9
+ - "[0-9]+.[0-9]+.[0-9]+rc[0-9]+"
10
+
11
+ env:
12
+ PACKAGE_NAME: "snakemake-logger-plugin-rich"
13
+ OWNER: "cademirch"
14
+
15
+ jobs:
16
+ details:
17
+ runs-on: ubuntu-latest
18
+ outputs:
19
+ new_version: ${{ steps.release.outputs.new_version }}
20
+ suffix: ${{ steps.release.outputs.suffix }}
21
+ tag_name: ${{ steps.release.outputs.tag_name }}
22
+ steps:
23
+ - uses: actions/checkout@v2
24
+
25
+ - name: Extract tag and Details
26
+ id: release
27
+ run: |
28
+ if [ "${{ github.ref_type }}" = "tag" ]; then
29
+ TAG_NAME=${GITHUB_REF#refs/tags/}
30
+ NEW_VERSION=$(echo $TAG_NAME | awk -F'-' '{print $1}')
31
+ SUFFIX=$(echo $TAG_NAME | grep -oP '[a-z]+[0-9]+' || echo "")
32
+ echo "new_version=$NEW_VERSION" >> "$GITHUB_OUTPUT"
33
+ echo "suffix=$SUFFIX" >> "$GITHUB_OUTPUT"
34
+ echo "tag_name=$TAG_NAME" >> "$GITHUB_OUTPUT"
35
+ echo "Version is $NEW_VERSION"
36
+ echo "Suffix is $SUFFIX"
37
+ echo "Tag name is $TAG_NAME"
38
+ else
39
+ echo "No tag found"
40
+ exit 1
41
+ fi
42
+
43
+ check_pypi:
44
+ needs: details
45
+ runs-on: ubuntu-latest
46
+ steps:
47
+ - name: Fetch information from PyPI
48
+ run: |
49
+ response=$(curl -s https://pypi.org/pypi/${{ env.PACKAGE_NAME }}/json || echo "{}")
50
+ latest_previous_version=$(echo $response | grep -oP '"releases":\{"\K[^"]+' | sort -rV | head -n 1)
51
+ if [ -z "$latest_previous_version" ]; then
52
+ echo "Package not found on PyPI."
53
+ latest_previous_version="0.0.0"
54
+ fi
55
+ echo "Latest version on PyPI: $latest_previous_version"
56
+ echo "latest_previous_version=$latest_previous_version" >> $GITHUB_ENV
57
+
58
+ - name: Compare versions and exit if not newer
59
+ run: |
60
+ NEW_VERSION=${{ needs.details.outputs.new_version }}
61
+ LATEST_VERSION=$latest_previous_version
62
+ if [ "$(printf '%s\n' "$LATEST_VERSION" "$NEW_VERSION" | sort -rV | head -n 1)" != "$NEW_VERSION" ] || [ "$NEW_VERSION" == "$LATEST_VERSION" ]; then
63
+ echo "The new version $NEW_VERSION is not greater than the latest version $LATEST_VERSION on PyPI."
64
+ exit 1
65
+ else
66
+ echo "The new version $NEW_VERSION is greater than the latest version $LATEST_VERSION on PyPI."
67
+ fi
68
+
69
+ setup_and_build:
70
+ needs: [details, check_pypi]
71
+ runs-on: ubuntu-latest
72
+ steps:
73
+ - uses: actions/checkout@v2
74
+
75
+ - name: Install uv
76
+ uses: astral-sh/setup-uv@v3
77
+
78
+ - name: "Set up Python"
79
+ uses: actions/setup-python@v5
80
+ with:
81
+ python-version-file: "pyproject.toml"
82
+
83
+ - name: Install the project
84
+ run: uv sync --all-extras --dev
85
+
86
+ - name: Build source and wheel distribution
87
+ run: |
88
+ uv build
89
+
90
+ - name: Upload artifacts
91
+ uses: actions/upload-artifact@v3
92
+ with:
93
+ name: dist
94
+ path: dist/
95
+
96
+ pypi_publish:
97
+ name: Upload release to PyPI
98
+ needs: [setup_and_build, details]
99
+ runs-on: ubuntu-latest
100
+ environment:
101
+ name: release
102
+ permissions:
103
+ id-token: write
104
+ steps:
105
+ - name: Download artifacts
106
+ uses: actions/download-artifact@v3
107
+ with:
108
+ name: dist
109
+ path: dist/
110
+
111
+ - name: Publish distribution to PyPI
112
+ uses: pypa/gh-action-pypi-publish@release/v1
113
+
114
+ github_release:
115
+ name: Create GitHub Release
116
+ needs: [setup_and_build, details]
117
+ runs-on: ubuntu-latest
118
+ permissions:
119
+ contents: write
120
+ steps:
121
+ - name: Checkout Code
122
+ uses: actions/checkout@v3
123
+ with:
124
+ fetch-depth: 0
125
+
126
+ - name: Download artifacts
127
+ uses: actions/download-artifact@v3
128
+ with:
129
+ name: dist
130
+ path: dist/
131
+
132
+ - name: Create GitHub Release
133
+ id: create_release
134
+ env:
135
+ GH_TOKEN: ${{ github.token }}
136
+ run: |
137
+ gh release create ${{ needs.details.outputs.tag_name }} dist/* --title ${{ needs.details.outputs.tag_name }} --generate-notes
@@ -0,0 +1,163 @@
1
+ ### Generated by gibo (https://github.com/simonwhitaker/gibo)
2
+ ### https://raw.github.com/github/gitignore/4488915eec0b3a45b5c63ead28f286819c0917de/Python.gitignore
3
+
4
+ # Byte-compiled / optimized / DLL files
5
+ __pycache__/
6
+ *.py[cod]
7
+ *$py.class
8
+
9
+ # C extensions
10
+ *.so
11
+
12
+ # Distribution / packaging
13
+ .Python
14
+ build/
15
+ develop-eggs/
16
+ dist/
17
+ downloads/
18
+ eggs/
19
+ .eggs/
20
+ lib/
21
+ lib64/
22
+ parts/
23
+ sdist/
24
+ var/
25
+ wheels/
26
+ share/python-wheels/
27
+ *.egg-info/
28
+ .installed.cfg
29
+ *.egg
30
+ MANIFEST
31
+
32
+ # PyInstaller
33
+ # Usually these files are written by a python script from a template
34
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
35
+ *.manifest
36
+ *.spec
37
+
38
+ # Installer logs
39
+ pip-log.txt
40
+ pip-delete-this-directory.txt
41
+
42
+ # Unit test / coverage reports
43
+ htmlcov/
44
+ .tox/
45
+ .nox/
46
+ .coverage
47
+ .coverage.*
48
+ .cache
49
+ nosetests.xml
50
+ coverage.xml
51
+ *.cover
52
+ *.py,cover
53
+ .hypothesis/
54
+ .pytest_cache/
55
+ cover/
56
+
57
+ # Translations
58
+ *.mo
59
+ *.pot
60
+
61
+ # Django stuff:
62
+ *.log
63
+ local_settings.py
64
+ db.sqlite3
65
+ db.sqlite3-journal
66
+
67
+ # Flask stuff:
68
+ instance/
69
+ .webassets-cache
70
+
71
+ # Scrapy stuff:
72
+ .scrapy
73
+
74
+ # Sphinx documentation
75
+ docs/_build/
76
+
77
+ # PyBuilder
78
+ .pybuilder/
79
+ target/
80
+
81
+ # Jupyter Notebook
82
+ .ipynb_checkpoints
83
+
84
+ # IPython
85
+ profile_default/
86
+ ipython_config.py
87
+
88
+ # pyenv
89
+ # For a library or package, you might want to ignore these files since the code is
90
+ # intended to run in multiple environments; otherwise, check them in:
91
+ # .python-version
92
+
93
+ # pipenv
94
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
95
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
96
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
97
+ # install all needed dependencies.
98
+ #Pipfile.lock
99
+
100
+ # poetry
101
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
102
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
103
+ # commonly ignored for libraries.
104
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
105
+ #poetry.lock
106
+
107
+ # pdm
108
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
109
+ #pdm.lock
110
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
111
+ # in version control.
112
+ # https://pdm.fming.dev/#use-with-ide
113
+ .pdm.toml
114
+
115
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
116
+ __pypackages__/
117
+
118
+ # Celery stuff
119
+ celerybeat-schedule
120
+ celerybeat.pid
121
+
122
+ # SageMath parsed files
123
+ *.sage.py
124
+
125
+ # Environments
126
+ .env
127
+ .venv
128
+ env/
129
+ venv/
130
+ ENV/
131
+ env.bak/
132
+ venv.bak/
133
+
134
+ # Spyder project settings
135
+ .spyderproject
136
+ .spyproject
137
+
138
+ # Rope project settings
139
+ .ropeproject
140
+
141
+ # mkdocs documentation
142
+ /site
143
+
144
+ # mypy
145
+ .mypy_cache/
146
+ .dmypy.json
147
+ dmypy.json
148
+
149
+ # Pyre type checker
150
+ .pyre/
151
+
152
+ # pytype static type analyzer
153
+ .pytype/
154
+
155
+ # Cython debug symbols
156
+ cython_debug/
157
+
158
+ # PyCharm
159
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
160
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
161
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
162
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
163
+ #.idea/
@@ -0,0 +1,5 @@
1
+ # Changelog
2
+
3
+ ## [0.1.0] - 2024-11-03
4
+
5
+ - Initial release.
@@ -0,0 +1,15 @@
1
+ Metadata-Version: 2.3
2
+ Name: snakemake-logger-plugin-rich
3
+ Version: 0.1.0
4
+ Summary: Log plugin for snakemake using Rich
5
+ Requires-Python: >=3.12
6
+ Requires-Dist: rich>=13.9.4
7
+ Requires-Dist: snakemake-interface-executor-plugins>=9.3.2
8
+ Requires-Dist: snakemake-interface-logger-plugins>=0.1.0
9
+ Description-Content-Type: text/markdown
10
+
11
+ # Snakemake Rich Logger Plugin
12
+
13
+ Proof of concept logger plugin that uses [rich](https://github.com/Textualize/rich) for terminal styling and progress bar.
14
+
15
+ Log formatting still needs lots of work but the progress bar works well.
@@ -0,0 +1,5 @@
1
+ # Snakemake Rich Logger Plugin
2
+
3
+ Proof of concept logger plugin that uses [rich](https://github.com/Textualize/rich) for terminal styling and progress bar.
4
+
5
+ Log formatting still needs lots of work but the progress bar works well.
@@ -0,0 +1,15 @@
1
+ [project]
2
+ name = "snakemake-logger-plugin-rich"
3
+ version = "0.1.0"
4
+ description = "Log plugin for snakemake using Rich"
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ dependencies = [
8
+ "rich>=13.9.4",
9
+ "snakemake-interface-executor-plugins>=9.3.2",
10
+ "snakemake-interface-logger-plugins>=0.1.0",
11
+ ]
12
+
13
+ [build-system]
14
+ requires = ["hatchling"]
15
+ build-backend = "hatchling.build"
@@ -0,0 +1,46 @@
1
+ from snakemake_interface_logger_plugins.base import LoggerPluginBase
2
+ from snakemake_logger_plugin_rich.handler import RichLogHandler
3
+ from logging import Handler, Formatter
4
+
5
+
6
+ class LoggerPlugin(LoggerPluginBase):
7
+ def __post__init(self) -> None:
8
+ """
9
+ Any additional setup after initialization.
10
+ """
11
+
12
+ def create_handler(
13
+ self,
14
+ quiet,
15
+ printshellcmds: bool,
16
+ printreason: bool,
17
+ debug_dag: bool,
18
+ nocolor: bool,
19
+ stdout: bool,
20
+ debug: bool,
21
+ mode,
22
+ show_failed_logs: bool,
23
+ dryrun: bool,
24
+ ) -> Handler:
25
+ """
26
+ Creates and returns an instance of RichLogHandler, configured with plugin settings.
27
+ """
28
+ # Initialize RichLogHandler with plugin settings
29
+ handler = RichLogHandler(
30
+ quiet=quiet,
31
+ printshellcmds=printshellcmds,
32
+ printreason=printreason,
33
+ debug_dag=debug_dag,
34
+ nocolor=nocolor,
35
+ stdout=stdout,
36
+ debug=debug,
37
+ mode=mode,
38
+ show_failed_logs=show_failed_logs,
39
+ dryrun=dryrun,
40
+ show_time=True,
41
+ show_path=False,
42
+ markup=False,
43
+ )
44
+ FORMAT = Formatter("%(message)s")
45
+ handler.setFormatter(FORMAT)
46
+ return handler
@@ -0,0 +1,139 @@
1
+ import logging
2
+ from rich.logging import RichHandler
3
+ from rich.progress import (
4
+ BarColumn,
5
+ MofNCompleteColumn,
6
+ Progress,
7
+ TextColumn,
8
+ TimeElapsedColumn,
9
+ TimeRemainingColumn,
10
+ )
11
+ from rich.console import Console
12
+ from typing import Optional
13
+ from snakemake_interface_executor_plugins.settings import ExecMode
14
+
15
+
16
+ class RichLogHandler(RichHandler):
17
+ """
18
+ A custom Rich handler for Snakemake logging with a persistent progress bar at the bottom.
19
+ """
20
+
21
+ def __init__(
22
+ self,
23
+ quiet=None,
24
+ printshellcmds: Optional[bool] = None,
25
+ printreason: Optional[bool] = None,
26
+ debug_dag: Optional[bool] = None,
27
+ nocolor: Optional[bool] = None,
28
+ stdout: Optional[bool] = None,
29
+ debug: Optional[bool] = None,
30
+ mode=None,
31
+ show_failed_logs: Optional[bool] = None,
32
+ dryrun: Optional[bool] = None,
33
+ *args,
34
+ **kwargs,
35
+ ):
36
+ console = Console(stderr=not stdout)
37
+ super().__init__(*args, **kwargs, console=console)
38
+
39
+ # Store additional configurations
40
+ self.quiet = quiet
41
+ self.printshellcmds = printshellcmds
42
+ self.printreason = printreason
43
+ self.debug_dag = debug_dag
44
+ self.nocolor = nocolor
45
+ self.stdout = stdout
46
+ self.debug = debug
47
+ self.mode = mode
48
+ self.show_failed_logs = show_failed_logs
49
+ self.dryrun = dryrun
50
+ self.stream = True
51
+
52
+ # Initialize the progress bar only if mode is not SUBPROCESS and not dryrun
53
+ if self.mode != ExecMode.SUBPROCESS and not self.dryrun:
54
+ self.progress = Progress(
55
+ TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
56
+ BarColumn(),
57
+ MofNCompleteColumn(),
58
+ TextColumn("•"),
59
+ TimeElapsedColumn(),
60
+ TextColumn("•"),
61
+ TimeRemainingColumn(),
62
+ console=console,
63
+ auto_refresh=True,
64
+ )
65
+ self.progress_task = None
66
+ self.total_steps = 1 # To avoid division errors if not set
67
+ else:
68
+ self.progress = None
69
+ self.progress_task = None
70
+
71
+ def start_progress_bar(self, total_steps):
72
+ """
73
+ Initialize and start the progress bar for a Snakemake job if progress is enabled.
74
+ """
75
+ if self.progress:
76
+ self.total_steps = total_steps
77
+ self.progress_task = self.progress.add_task(
78
+ "Processing...", total=total_steps
79
+ )
80
+
81
+ def get_level(self, record: logging.LogRecord) -> str:
82
+ """
83
+ Gets snakemake log level from a log record. If there is no snakemake log level,
84
+ returns the log record's level name.
85
+
86
+ Args:
87
+ record (logging.LogRecord)
88
+ Returns:
89
+ str: The log level
90
+
91
+ """
92
+ level = record.__dict__.get("level", None)
93
+
94
+ if level is None:
95
+ level = record.levelname
96
+
97
+ return level.lower()
98
+
99
+ def update_progress(self, done_steps):
100
+ """
101
+ Update the progress bar with the number of completed steps.
102
+ """
103
+ if self.progress and self.progress_task is not None:
104
+ self.progress.update(self.progress_task, completed=done_steps)
105
+
106
+ def emit(self, record):
107
+ """
108
+ Emit log messages with Rich formatting and update the progress bar if necessary.
109
+ """
110
+ message = self.format(record)
111
+ level = self.get_level(record)
112
+
113
+ if level == "progress" and self.progress:
114
+ done_steps = getattr(record, "done", 0)
115
+ total_steps = getattr(record, "total", self.total_steps)
116
+ if self.progress_task is None:
117
+ # Start progress bar if this is the first progress log
118
+ self.total_steps = total_steps
119
+ self.progress_task = self.progress.add_task(
120
+ "Processing...", total=total_steps
121
+ )
122
+ self.progress.start()
123
+ # Update the progress bar
124
+ self.progress.update(self.progress_task, completed=done_steps)
125
+ if level == "run_info":
126
+ record.message.replace("\n", "")
127
+ else:
128
+ super().emit(record)
129
+
130
+ def close(self):
131
+ """
132
+ Ensure progress bar is stopped and cleaned up on handler close.
133
+ """
134
+ if self.progress:
135
+ self.progress.stop()
136
+ if self.progress_task is not None:
137
+ self.progress.remove_task(self.progress_task)
138
+ self.progress_task = None
139
+ super().close()
@@ -0,0 +1,128 @@
1
+ version = 1
2
+ requires-python = ">=3.12"
3
+
4
+ [[package]]
5
+ name = "argparse-dataclass"
6
+ version = "2.0.0"
7
+ source = { registry = "https://pypi.org/simple" }
8
+ sdist = { url = "https://files.pythonhosted.org/packages/1a/ff/a2e4e328075ddef2ac3c9431eb12247e4ba707a70324894f1e6b4f43c286/argparse_dataclass-2.0.0.tar.gz", hash = "sha256:09ab641c914a2f12882337b9c3e5086196dbf2ee6bf0ef67895c74002cc9297f", size = 6395 }
9
+ wheels = [
10
+ { url = "https://files.pythonhosted.org/packages/b3/66/e6c0a808950ba5a4042e2fcedd577fc7401536c7db063de4d7c36be06f84/argparse_dataclass-2.0.0-py3-none-any.whl", hash = "sha256:3ffc8852a88d9d98d1364b4441a712491320afb91fb56049afd8a51d74bb52d2", size = 8762 },
11
+ ]
12
+
13
+ [[package]]
14
+ name = "configargparse"
15
+ version = "1.7"
16
+ source = { registry = "https://pypi.org/simple" }
17
+ sdist = { url = "https://files.pythonhosted.org/packages/70/8a/73f1008adfad01cb923255b924b1528727b8270e67cb4ef41eabdc7d783e/ConfigArgParse-1.7.tar.gz", hash = "sha256:e7067471884de5478c58a511e529f0f9bd1c66bfef1dea90935438d6c23306d1", size = 43817 }
18
+ wheels = [
19
+ { url = "https://files.pythonhosted.org/packages/6f/b3/b4ac838711fd74a2b4e6f746703cf9dd2cf5462d17dac07e349234e21b97/ConfigArgParse-1.7-py3-none-any.whl", hash = "sha256:d249da6591465c6c26df64a9f73d2536e743be2f244eb3ebe61114af2f94f86b", size = 25489 },
20
+ ]
21
+
22
+ [[package]]
23
+ name = "markdown-it-py"
24
+ version = "3.0.0"
25
+ source = { registry = "https://pypi.org/simple" }
26
+ dependencies = [
27
+ { name = "mdurl" },
28
+ ]
29
+ sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 }
30
+ wheels = [
31
+ { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 },
32
+ ]
33
+
34
+ [[package]]
35
+ name = "mdurl"
36
+ version = "0.1.2"
37
+ source = { registry = "https://pypi.org/simple" }
38
+ sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 }
39
+ wheels = [
40
+ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 },
41
+ ]
42
+
43
+ [[package]]
44
+ name = "pygments"
45
+ version = "2.18.0"
46
+ source = { registry = "https://pypi.org/simple" }
47
+ sdist = { url = "https://files.pythonhosted.org/packages/8e/62/8336eff65bcbc8e4cb5d05b55faf041285951b6e80f33e2bff2024788f31/pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199", size = 4891905 }
48
+ wheels = [
49
+ { url = "https://files.pythonhosted.org/packages/f7/3f/01c8b82017c199075f8f788d0d906b9ffbbc5a47dc9918a945e13d5a2bda/pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a", size = 1205513 },
50
+ ]
51
+
52
+ [[package]]
53
+ name = "rich"
54
+ version = "13.9.4"
55
+ source = { registry = "https://pypi.org/simple" }
56
+ dependencies = [
57
+ { name = "markdown-it-py" },
58
+ { name = "pygments" },
59
+ ]
60
+ sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 }
61
+ wheels = [
62
+ { url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 },
63
+ ]
64
+
65
+ [[package]]
66
+ name = "snakemake-interface-common"
67
+ version = "1.17.4"
68
+ source = { registry = "https://pypi.org/simple" }
69
+ dependencies = [
70
+ { name = "argparse-dataclass" },
71
+ { name = "configargparse" },
72
+ ]
73
+ sdist = { url = "https://files.pythonhosted.org/packages/09/d4/dd2694226160c126e3ce2a27222088bde3ef07cd554d31d63398cc48f810/snakemake_interface_common-1.17.4.tar.gz", hash = "sha256:c2142e1b93cbc18c2cf41d15968ba8688f60b077c8284e5de057cccfc215d4d3", size = 9897 }
74
+ wheels = [
75
+ { url = "https://files.pythonhosted.org/packages/3d/fe/c318657e6a4b8ab5b3eafa07cd1c360a732c6b37ba6085f3c82339ebbbdc/snakemake_interface_common-1.17.4-py3-none-any.whl", hash = "sha256:1d757cce0300a73d48b906d1ade38706853169320a5d27b963869888d130c354", size = 14011 },
76
+ ]
77
+
78
+ [[package]]
79
+ name = "snakemake-interface-executor-plugins"
80
+ version = "9.3.2"
81
+ source = { registry = "https://pypi.org/simple" }
82
+ dependencies = [
83
+ { name = "argparse-dataclass" },
84
+ { name = "snakemake-interface-common" },
85
+ { name = "throttler" },
86
+ ]
87
+ sdist = { url = "https://files.pythonhosted.org/packages/6f/77/f3e7a7abff8f15bd50f168eef1e3153167a681bfd51a454a3adb0918cb8d/snakemake_interface_executor_plugins-9.3.2.tar.gz", hash = "sha256:19c50dc82989ff25d10386cfb3c99da9d2dc980d95ecd30bbb431374dcd390b3", size = 16714 }
88
+ wheels = [
89
+ { url = "https://files.pythonhosted.org/packages/7c/84/0b7602c54d97b2cd3b40fc4c80633d42afcf69e441d9f25c928376051be8/snakemake_interface_executor_plugins-9.3.2-py3-none-any.whl", hash = "sha256:9c52c4b0f74b9056ebbb1b6229459281fef002b678baac00aee3b3ef36e92ba5", size = 22389 },
90
+ ]
91
+
92
+ [[package]]
93
+ name = "snakemake-interface-logger-plugins"
94
+ version = "0.1.0"
95
+ source = { registry = "https://pypi.org/simple" }
96
+ dependencies = [
97
+ { name = "snakemake-interface-common" },
98
+ ]
99
+ sdist = { url = "https://files.pythonhosted.org/packages/e0/bf/3a2ec00e575f5d9937af6304f22695901dfb28141e6f14657baad98665b1/snakemake_interface_logger_plugins-0.1.0.tar.gz", hash = "sha256:87091a471cae9807a73e4b89983e9eed39db03427c448fe6c09b42b3d9cfed4d", size = 5906 }
100
+ wheels = [
101
+ { url = "https://files.pythonhosted.org/packages/46/2f/8cdfa7306c38861517eb2ecef198f85b32eb6dec9ecf53209efaf70a9b1b/snakemake_interface_logger_plugins-0.1.0-py3-none-any.whl", hash = "sha256:c18ed71726ff9f463a3b914ba130eab032ffcc6daca38c106fa0a9d5e9086dc1", size = 4706 },
102
+ ]
103
+
104
+ [[package]]
105
+ name = "snakemake-logger-plugin-rich"
106
+ version = "0.1.0"
107
+ source = { editable = "." }
108
+ dependencies = [
109
+ { name = "rich" },
110
+ { name = "snakemake-interface-executor-plugins" },
111
+ { name = "snakemake-interface-logger-plugins" },
112
+ ]
113
+
114
+ [package.metadata]
115
+ requires-dist = [
116
+ { name = "rich", specifier = ">=13.9.4" },
117
+ { name = "snakemake-interface-executor-plugins", specifier = ">=9.3.2" },
118
+ { name = "snakemake-interface-logger-plugins", specifier = ">=0.1.0" },
119
+ ]
120
+
121
+ [[package]]
122
+ name = "throttler"
123
+ version = "1.2.2"
124
+ source = { registry = "https://pypi.org/simple" }
125
+ sdist = { url = "https://files.pythonhosted.org/packages/b4/22/638451122136d5280bc477c8075ea448b9ebdfbd319f0f120edaecea2038/throttler-1.2.2.tar.gz", hash = "sha256:d54db406d98e1b54d18a9ba2b31ab9f093ac64a0a59d730c1cf7bb1cdfc94a58", size = 7970 }
126
+ wheels = [
127
+ { url = "https://files.pythonhosted.org/packages/df/d4/36bf6010b184286000b2334622bfb3446a40c22c1d2a9776bff025cb0fe5/throttler-1.2.2-py3-none-any.whl", hash = "sha256:fc6ae612a2529e01110b32335af40375258b98e3b81232ec77cd07f51bf71392", size = 7609 },
128
+ ]