abstract-block-dumper 0.0.1__tar.gz → 0.0.2__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.
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/CHANGELOG.md +5 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/PKG-INFO +22 -6
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/README.md +21 -5
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/README.md +1 -1
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/block_explorer/tasks.py +1 -1
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/docker-compose.yml +1 -1
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/example_project/settings.py +10 -0
- {abstract_block_dumper-0.0.1/src/abstract_block_dumper → abstract_block_dumper-0.0.2/src/abstract_block_dumper/_internal}/dal/django_dal.py +4 -3
- {abstract_block_dumper-0.0.1/src/abstract_block_dumper → abstract_block_dumper-0.0.2/src/abstract_block_dumper/_internal}/dal/memory_registry.py +6 -14
- {abstract_block_dumper-0.0.1/src/abstract_block_dumper → abstract_block_dumper-0.0.2/src/abstract_block_dumper/_internal}/discovery.py +1 -1
- {abstract_block_dumper-0.0.1/src/abstract_block_dumper → abstract_block_dumper-0.0.2/src/abstract_block_dumper/_internal}/exceptions.py +1 -1
- {abstract_block_dumper-0.0.1/src/abstract_block_dumper → abstract_block_dumper-0.0.2/src/abstract_block_dumper/_internal}/services/block_processor.py +6 -5
- {abstract_block_dumper-0.0.1/src/abstract_block_dumper → abstract_block_dumper-0.0.2/src/abstract_block_dumper/_internal}/services/executor.py +2 -2
- {abstract_block_dumper-0.0.1/src/abstract_block_dumper → abstract_block_dumper-0.0.2/src/abstract_block_dumper/_internal}/services/scheduler.py +3 -3
- {abstract_block_dumper-0.0.1/src/abstract_block_dumper → abstract_block_dumper-0.0.2/src/abstract_block_dumper/_internal}/services/utils.py +3 -7
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/src/abstract_block_dumper/_version.py +2 -2
- abstract_block_dumper-0.0.1/src/abstract_block_dumper/management/commands/block_tasks.py → abstract_block_dumper-0.0.2/src/abstract_block_dumper/management/commands/block_tasks_v1.py +3 -3
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/src/abstract_block_dumper/models.py +1 -1
- {abstract_block_dumper-0.0.1/src/abstract_block_dumper → abstract_block_dumper-0.0.2/src/abstract_block_dumper/v1}/decorators.py +7 -8
- {abstract_block_dumper-0.0.1/src/abstract_block_dumper → abstract_block_dumper-0.0.2/src/abstract_block_dumper/v1}/tasks.py +3 -3
- abstract_block_dumper-0.0.2/tests/__init__.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/tests/conftest.py +2 -2
- abstract_block_dumper-0.0.2/tests/integration/__init__.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/tests/integration/test_block_processor.py +3 -3
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/tests/integration/test_concurrent_processing.py +6 -6
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/tests/integration/test_multi_arguments_tasks.py +4 -4
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/tests/integration/test_registered_celery_tasks.py +5 -5
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/tests/integration/test_scheduler.py +5 -5
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/tests/integration/test_task_registration.py +4 -4
- abstract_block_dumper-0.0.2/tests/unit/test_decorator.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/.cruft.json +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/.github/dependabot.yml +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/.github/workflows/ci.yml +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/.github/workflows/publish.yml +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/.gitignore +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/.pre-commit-config.yaml +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/.shellcheckrc +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/SECURITY.md +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/docs/3rd_party/cookiecutter-rt-pkg/CHANGELOG.md +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/.dockerignore +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/.gitignore +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/Dockerfile +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/block_explorer/__init__.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/block_explorer/admin.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/block_explorer/apps.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/block_explorer/management/__init__.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/block_explorer/management/commands/__init__.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/block_explorer/management/commands/create_admin.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/block_explorer/migrations/__init__.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/block_explorer/models.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/block_explorer/tests.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/block_explorer/views.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/example_project/__init__.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/example_project/asgi.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/example_project/celery.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/example_project/urls.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/example_project/wsgi.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/main.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/manage.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/pyproject.toml +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/pytest.ini +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/uv.lock +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/noxfile.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/pyproject.toml +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/src/abstract_block_dumper/__init__.py +0 -0
- {abstract_block_dumper-0.0.1/src/abstract_block_dumper/dal → abstract_block_dumper-0.0.2/src/abstract_block_dumper/_internal}/__init__.py +0 -0
- {abstract_block_dumper-0.0.1/src/abstract_block_dumper/management → abstract_block_dumper-0.0.2/src/abstract_block_dumper/_internal/dal}/__init__.py +0 -0
- {abstract_block_dumper-0.0.1/src/abstract_block_dumper/migrations → abstract_block_dumper-0.0.2/src/abstract_block_dumper/_internal/services}/__init__.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/src/abstract_block_dumper/admin.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/src/abstract_block_dumper/apps.py +0 -0
- {abstract_block_dumper-0.0.1/src/abstract_block_dumper/services → abstract_block_dumper-0.0.2/src/abstract_block_dumper/management}/__init__.py +0 -0
- {abstract_block_dumper-0.0.1/tests → abstract_block_dumper-0.0.2/src/abstract_block_dumper/management/commands}/__init__.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/src/abstract_block_dumper/migrations/0001_initial.py +0 -0
- {abstract_block_dumper-0.0.1/tests/integration → abstract_block_dumper-0.0.2/src/abstract_block_dumper/migrations}/__init__.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/src/abstract_block_dumper/py.typed +0 -0
- /abstract_block_dumper-0.0.1/tests/unit/test_decorator.py → /abstract_block_dumper-0.0.2/src/abstract_block_dumper/v1/__init__.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/tests/django_fixtures.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/tests/fatories.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/tests/settings.py +0 -0
- {abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/uv.lock +0 -0
|
@@ -9,6 +9,11 @@ upcoming release can be found in [changelog.d](changelog.d).
|
|
|
9
9
|
|
|
10
10
|
<!-- towncrier release notes start -->
|
|
11
11
|
|
|
12
|
+
## [0.0.2](https://github.com/bactensor/abstract-block-dumper/releases/tag/v0.0.2) - 2025-10-24
|
|
13
|
+
|
|
14
|
+
No significant changes.
|
|
15
|
+
|
|
16
|
+
|
|
12
17
|
## [0.0.1](https://github.com/bactensor/abstract-block-dumper/releases/tag/v0.0.1) - 2025-10-21
|
|
13
18
|
|
|
14
19
|
No significant changes.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: abstract-block-dumper
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.2
|
|
4
4
|
Project-URL: Source, https://github.com/bactensor/abstract-block-dumper
|
|
5
5
|
Project-URL: Issue Tracker, https://github.com/bactensor/abstract-block-dumper/issues
|
|
6
6
|
Author-email: Reef Technologies <opensource@reef.pl>
|
|
@@ -26,6 +26,22 @@ Description-Content-Type: text/markdown
|
|
|
26
26
|
This package provides a simplified framework for creating block processing tasks in Django applications.
|
|
27
27
|
Define tasks with lambda conditions using the @block_task decorator and run them asynchronously with Celery.
|
|
28
28
|
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
> [!IMPORTANT]
|
|
32
|
+
> This package uses [ApiVer](#versioning), make sure to import `abstract_block_dumper.v1`.
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
## Versioning
|
|
36
|
+
|
|
37
|
+
This package uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
38
|
+
TL;DR you are safe to use [compatible release version specifier](https://packaging.python.org/en/latest/specifications/version-specifiers/#compatible-release) `~=MAJOR.MINOR` in your `pyproject.toml` or `requirements.txt`.
|
|
39
|
+
|
|
40
|
+
Additionally, this package uses [ApiVer](https://www.youtube.com/watch?v=FgcoAKchPjk) to further reduce the risk of breaking changes.
|
|
41
|
+
This means, the public API of this package is explicitly versioned, e.g. `abstract_block_dumper.v1`, and will not change in a backwards-incompatible way even when `abstract_block_dumper.v2` is released.
|
|
42
|
+
|
|
43
|
+
Internal packages, i.e. prefixed by `abstract_block_dumper._` do not share these guarantees and may change in a backwards-incompatible way at any time even in patch releases.
|
|
44
|
+
|
|
29
45
|
## Implementation Details
|
|
30
46
|
|
|
31
47
|
### General Workflow:
|
|
@@ -93,7 +109,7 @@ Create block processing tasks in `tasks.py` or `block_tasks.py` file inside any
|
|
|
93
109
|
### 3. Start the Block Scheduler
|
|
94
110
|
Run the scheduler to start processing blocks:
|
|
95
111
|
```bash
|
|
96
|
-
$ python manage.py
|
|
112
|
+
$ python manage.py block_tasks_v1
|
|
97
113
|
```
|
|
98
114
|
|
|
99
115
|
This command will:
|
|
@@ -112,7 +128,7 @@ See examples below:
|
|
|
112
128
|
Use the `@block_task` decorator with lambda conditions to create block processing tasks:
|
|
113
129
|
|
|
114
130
|
```python
|
|
115
|
-
from abstract_block_dumper.decorators import block_task
|
|
131
|
+
from abstract_block_dumper.api.v1.decorators import block_task
|
|
116
132
|
|
|
117
133
|
|
|
118
134
|
# Process every block
|
|
@@ -144,7 +160,7 @@ def process_multi_netuid_task(block_number: int, netuid: int):
|
|
|
144
160
|
The framework provides a maintenance task to clean up old task records and maintain database performance:
|
|
145
161
|
|
|
146
162
|
```python
|
|
147
|
-
from abstract_block_dumper.tasks import cleanup_old_tasks
|
|
163
|
+
from abstract_block_dumper.v1.tasks import cleanup_old_tasks
|
|
148
164
|
|
|
149
165
|
# Delete tasks older than 7 days (default)
|
|
150
166
|
cleanup_old_tasks.delay()
|
|
@@ -160,13 +176,13 @@ This task deletes all succeeded or unrecoverable failed tasks older than the spe
|
|
|
160
176
|
**Option 1: Manual Execution**
|
|
161
177
|
```bash
|
|
162
178
|
# Using Django shell
|
|
163
|
-
python manage.py shell -c "from abstract_block_dumper.tasks import cleanup_old_tasks; cleanup_old_tasks.delay()"
|
|
179
|
+
python manage.py shell -c "from abstract_block_dumper.v1.tasks import cleanup_old_tasks; cleanup_old_tasks.delay()"
|
|
164
180
|
```
|
|
165
181
|
|
|
166
182
|
**Option 2: Cron Job (Recommended - once per day)**
|
|
167
183
|
```bash
|
|
168
184
|
# Add to crontab (daily at 2 AM)
|
|
169
|
-
0 2 * * * cd /path/to/your/project && python manage.py shell -c "from abstract_block_dumper.tasks import cleanup_old_tasks; cleanup_old_tasks.delay()"
|
|
185
|
+
0 2 * * * cd /path/to/your/project && python manage.py shell -c "from abstract_block_dumper.v1.tasks import cleanup_old_tasks; cleanup_old_tasks.delay()"
|
|
170
186
|
```
|
|
171
187
|
|
|
172
188
|
**Option 3: Celery Beat (Automated Scheduling)**
|
|
@@ -4,6 +4,22 @@
|
|
|
4
4
|
This package provides a simplified framework for creating block processing tasks in Django applications.
|
|
5
5
|
Define tasks with lambda conditions using the @block_task decorator and run them asynchronously with Celery.
|
|
6
6
|
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
> [!IMPORTANT]
|
|
10
|
+
> This package uses [ApiVer](#versioning), make sure to import `abstract_block_dumper.v1`.
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## Versioning
|
|
14
|
+
|
|
15
|
+
This package uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
16
|
+
TL;DR you are safe to use [compatible release version specifier](https://packaging.python.org/en/latest/specifications/version-specifiers/#compatible-release) `~=MAJOR.MINOR` in your `pyproject.toml` or `requirements.txt`.
|
|
17
|
+
|
|
18
|
+
Additionally, this package uses [ApiVer](https://www.youtube.com/watch?v=FgcoAKchPjk) to further reduce the risk of breaking changes.
|
|
19
|
+
This means, the public API of this package is explicitly versioned, e.g. `abstract_block_dumper.v1`, and will not change in a backwards-incompatible way even when `abstract_block_dumper.v2` is released.
|
|
20
|
+
|
|
21
|
+
Internal packages, i.e. prefixed by `abstract_block_dumper._` do not share these guarantees and may change in a backwards-incompatible way at any time even in patch releases.
|
|
22
|
+
|
|
7
23
|
## Implementation Details
|
|
8
24
|
|
|
9
25
|
### General Workflow:
|
|
@@ -71,7 +87,7 @@ Create block processing tasks in `tasks.py` or `block_tasks.py` file inside any
|
|
|
71
87
|
### 3. Start the Block Scheduler
|
|
72
88
|
Run the scheduler to start processing blocks:
|
|
73
89
|
```bash
|
|
74
|
-
$ python manage.py
|
|
90
|
+
$ python manage.py block_tasks_v1
|
|
75
91
|
```
|
|
76
92
|
|
|
77
93
|
This command will:
|
|
@@ -90,7 +106,7 @@ See examples below:
|
|
|
90
106
|
Use the `@block_task` decorator with lambda conditions to create block processing tasks:
|
|
91
107
|
|
|
92
108
|
```python
|
|
93
|
-
from abstract_block_dumper.decorators import block_task
|
|
109
|
+
from abstract_block_dumper.api.v1.decorators import block_task
|
|
94
110
|
|
|
95
111
|
|
|
96
112
|
# Process every block
|
|
@@ -122,7 +138,7 @@ def process_multi_netuid_task(block_number: int, netuid: int):
|
|
|
122
138
|
The framework provides a maintenance task to clean up old task records and maintain database performance:
|
|
123
139
|
|
|
124
140
|
```python
|
|
125
|
-
from abstract_block_dumper.tasks import cleanup_old_tasks
|
|
141
|
+
from abstract_block_dumper.v1.tasks import cleanup_old_tasks
|
|
126
142
|
|
|
127
143
|
# Delete tasks older than 7 days (default)
|
|
128
144
|
cleanup_old_tasks.delay()
|
|
@@ -138,13 +154,13 @@ This task deletes all succeeded or unrecoverable failed tasks older than the spe
|
|
|
138
154
|
**Option 1: Manual Execution**
|
|
139
155
|
```bash
|
|
140
156
|
# Using Django shell
|
|
141
|
-
python manage.py shell -c "from abstract_block_dumper.tasks import cleanup_old_tasks; cleanup_old_tasks.delay()"
|
|
157
|
+
python manage.py shell -c "from abstract_block_dumper.v1.tasks import cleanup_old_tasks; cleanup_old_tasks.delay()"
|
|
142
158
|
```
|
|
143
159
|
|
|
144
160
|
**Option 2: Cron Job (Recommended - once per day)**
|
|
145
161
|
```bash
|
|
146
162
|
# Add to crontab (daily at 2 AM)
|
|
147
|
-
0 2 * * * cd /path/to/your/project && python manage.py shell -c "from abstract_block_dumper.tasks import cleanup_old_tasks; cleanup_old_tasks.delay()"
|
|
163
|
+
0 2 * * * cd /path/to/your/project && python manage.py shell -c "from abstract_block_dumper.v1.tasks import cleanup_old_tasks; cleanup_old_tasks.delay()"
|
|
148
164
|
```
|
|
149
165
|
|
|
150
166
|
**Option 3: Celery Beat (Automated Scheduling)**
|
|
@@ -15,5 +15,5 @@ docker-compose up --build
|
|
|
15
15
|
2. Access the Django admin interface at `http://localhost:8000/admin` with username `admin` and password `admin` (automatically created).
|
|
16
16
|
3. Start the block dumper scheduler:
|
|
17
17
|
```bash
|
|
18
|
-
docker-compose exec web python manage.py
|
|
18
|
+
docker-compose exec web python manage.py block_tasks_v1
|
|
19
19
|
```
|
|
@@ -3,6 +3,7 @@ import sys
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
5
|
import dj_database_url # type: ignore
|
|
6
|
+
from celery.schedules import crontab
|
|
6
7
|
|
|
7
8
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
|
8
9
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
|
@@ -133,3 +134,12 @@ BLOCK_DUMPER_POLL_INTERVAL = 1 # seconds - ultra-fast polling for real-time pro
|
|
|
133
134
|
BLOCK_DUMPER_START_FROM_BLOCK = "current" # None = resume from DB, 'current' = current block, or block number
|
|
134
135
|
BLOCK_TASK_RETRY_BACKOFF = 2
|
|
135
136
|
BLOCK_DUMPER_MAX_ATTEMPTS = 3
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
CELERY_BEAT_SCHEDULE = {
|
|
140
|
+
"cleanup-old-tasks": {
|
|
141
|
+
"task": "abstract_block_dumper.cleanup_old_tasks",
|
|
142
|
+
"schedule": crontab(hour=2, minute=0), # Daily at 2 AM
|
|
143
|
+
"kwargs": {"days": 7}, # Customize retention period
|
|
144
|
+
},
|
|
145
|
+
}
|
|
@@ -6,8 +6,8 @@ from django.db import transaction
|
|
|
6
6
|
from django.db.models.query import QuerySet
|
|
7
7
|
from django.utils import timezone
|
|
8
8
|
|
|
9
|
+
import abstract_block_dumper._internal.services.utils as abd_utils
|
|
9
10
|
import abstract_block_dumper.models as abd_models
|
|
10
|
-
import abstract_block_dumper.services.utils as abd_utils
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def get_ready_to_retry_attempts() -> QuerySet[abd_models.TaskAttempt]:
|
|
@@ -76,7 +76,7 @@ def task_mark_as_success(task: abd_models.TaskAttempt, result_data: dict) -> Non
|
|
|
76
76
|
task.save()
|
|
77
77
|
|
|
78
78
|
|
|
79
|
-
def task_mark_as_failed(task) -> None:
|
|
79
|
+
def task_mark_as_failed(task: abd_models.TaskAttempt) -> None:
|
|
80
80
|
DEFAULT_BLOCK_TASK_RETRY_BACKOFF = 1
|
|
81
81
|
MAX_RETRY_DELAY_MINUTES = 1440 # 24 hours max delay
|
|
82
82
|
|
|
@@ -98,7 +98,7 @@ def task_mark_as_failed(task) -> None:
|
|
|
98
98
|
task.save()
|
|
99
99
|
|
|
100
100
|
|
|
101
|
-
def task_schedule_to_retry(task):
|
|
101
|
+
def task_schedule_to_retry(task: abd_models.TaskAttempt) -> None:
|
|
102
102
|
task.status = abd_models.TaskAttempt.Status.PENDING
|
|
103
103
|
task.save()
|
|
104
104
|
|
|
@@ -110,6 +110,7 @@ def task_create_or_get_pending(
|
|
|
110
110
|
) -> tuple[abd_models.TaskAttempt, bool]:
|
|
111
111
|
"""
|
|
112
112
|
Create or get a pending task attempt.
|
|
113
|
+
|
|
113
114
|
Returns (task, created) where created indicates if a new task was created.
|
|
114
115
|
|
|
115
116
|
For failed tasks that can retry:
|
|
@@ -6,7 +6,7 @@ from typing import Any
|
|
|
6
6
|
import structlog
|
|
7
7
|
from celery import Task
|
|
8
8
|
|
|
9
|
-
from abstract_block_dumper.exceptions import ConditionEvaluationError
|
|
9
|
+
from abstract_block_dumper._internal.exceptions import ConditionEvaluationError
|
|
10
10
|
|
|
11
11
|
logger = structlog.getLogger(__name__)
|
|
12
12
|
|
|
@@ -19,10 +19,8 @@ class RegistryItem:
|
|
|
19
19
|
backfilling_lookback: int | None = None
|
|
20
20
|
celery_kwargs: dict[str, Any] = field(default_factory=dict)
|
|
21
21
|
|
|
22
|
-
def match_condition(self, block_number: int, **kwargs) -> bool:
|
|
23
|
-
"""
|
|
24
|
-
Check if condition matches for given block and arguments
|
|
25
|
-
"""
|
|
22
|
+
def match_condition(self, block_number: int, **kwargs: dict[str, Any]) -> bool:
|
|
23
|
+
"""Check if condition matches for given block and arguments."""
|
|
26
24
|
try:
|
|
27
25
|
return self.condition(block_number, **kwargs)
|
|
28
26
|
except Exception as e:
|
|
@@ -35,25 +33,19 @@ class RegistryItem:
|
|
|
35
33
|
raise ConditionEvaluationError(f"Failed to evaluate condition: {e}") from e
|
|
36
34
|
|
|
37
35
|
def get_execution_args(self) -> list[dict[str, Any]]:
|
|
38
|
-
"""
|
|
39
|
-
Get list of argument sets for execution
|
|
40
|
-
"""
|
|
36
|
+
"""Get list of argument sets for execution."""
|
|
41
37
|
return self.args or [{}]
|
|
42
38
|
|
|
43
39
|
@property
|
|
44
40
|
def executable_path(self) -> str:
|
|
45
|
-
"""
|
|
46
|
-
Get the importable path to the function.
|
|
47
|
-
"""
|
|
41
|
+
"""Get the importable path to the function."""
|
|
48
42
|
if hasattr(self.function, "name") and self.function.name is not None:
|
|
49
43
|
return self.function.name
|
|
50
44
|
|
|
51
45
|
return ".".join([self.function.__module__, self.function.__name__])
|
|
52
46
|
|
|
53
47
|
def requires_backfilling(self) -> bool:
|
|
54
|
-
"""
|
|
55
|
-
Check if this item requires backfilling.
|
|
56
|
-
"""
|
|
48
|
+
"""Check if this item requires backfilling."""
|
|
57
49
|
return self.backfilling_lookback is not None
|
|
58
50
|
|
|
59
51
|
|
|
@@ -11,7 +11,7 @@ def ensure_modules_loaded() -> None:
|
|
|
11
11
|
|
|
12
12
|
@block_task must be loaded, otherwise it won't be registered.
|
|
13
13
|
"""
|
|
14
|
-
from django.apps import apps
|
|
14
|
+
from django.apps import apps # noqa: PLC0415
|
|
15
15
|
|
|
16
16
|
for app_config in apps.get_app_configs():
|
|
17
17
|
for module_suffix in ["tasks", "block_tasks"]:
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import structlog
|
|
2
2
|
from django.db import transaction
|
|
3
3
|
|
|
4
|
-
import abstract_block_dumper.dal.django_dal as abd_dal
|
|
5
|
-
from abstract_block_dumper.dal.memory_registry import BaseRegistry, RegistryItem, task_registry
|
|
6
|
-
from abstract_block_dumper.exceptions import ConditionEvaluationError
|
|
4
|
+
import abstract_block_dumper._internal.dal.django_dal as abd_dal
|
|
5
|
+
from abstract_block_dumper._internal.dal.memory_registry import BaseRegistry, RegistryItem, task_registry
|
|
6
|
+
from abstract_block_dumper._internal.exceptions import ConditionEvaluationError
|
|
7
|
+
from abstract_block_dumper._internal.services.executor import CeleryExecutor
|
|
8
|
+
from abstract_block_dumper._internal.services.utils import serialize_args
|
|
7
9
|
from abstract_block_dumper.models import TaskAttempt
|
|
8
|
-
from abstract_block_dumper.services.executor import CeleryExecutor
|
|
9
|
-
from abstract_block_dumper.services.utils import serialize_args
|
|
10
10
|
|
|
11
11
|
logger = structlog.get_logger(__name__)
|
|
12
12
|
|
|
@@ -170,6 +170,7 @@ class BlockProcessor:
|
|
|
170
170
|
def _cleanup_phantom_tasks(self) -> None:
|
|
171
171
|
"""
|
|
172
172
|
Clean up tasks marked as SUCCESS but never actually started.
|
|
173
|
+
|
|
173
174
|
Only removes tasks that were created recently (within last hour) to avoid
|
|
174
175
|
deleting legitimate tasks marked as success by external processes.
|
|
175
176
|
"""
|
|
@@ -2,8 +2,8 @@ from typing import Any
|
|
|
2
2
|
|
|
3
3
|
import structlog
|
|
4
4
|
|
|
5
|
-
import abstract_block_dumper.dal.django_dal as abd_dal
|
|
6
|
-
from abstract_block_dumper.dal.memory_registry import RegistryItem
|
|
5
|
+
import abstract_block_dumper._internal.dal.django_dal as abd_dal
|
|
6
|
+
from abstract_block_dumper._internal.dal.memory_registry import RegistryItem
|
|
7
7
|
from abstract_block_dumper.models import TaskAttempt
|
|
8
8
|
|
|
9
9
|
logger = structlog.get_logger(__name__)
|
|
@@ -4,9 +4,9 @@ import bittensor as bt
|
|
|
4
4
|
import structlog
|
|
5
5
|
from django.conf import settings
|
|
6
6
|
|
|
7
|
-
import abstract_block_dumper.dal.django_dal as abd_dal
|
|
8
|
-
import abstract_block_dumper.services.utils as abd_utils
|
|
9
|
-
from abstract_block_dumper.services.block_processor import BlockProcessor, block_processor_factory
|
|
7
|
+
import abstract_block_dumper._internal.dal.django_dal as abd_dal
|
|
8
|
+
import abstract_block_dumper._internal.services.utils as abd_utils
|
|
9
|
+
from abstract_block_dumper._internal.services.block_processor import BlockProcessor, block_processor_factory
|
|
10
10
|
|
|
11
11
|
logger = structlog.get_logger(__name__)
|
|
12
12
|
|
|
@@ -20,14 +20,12 @@ def get_bittensor_client() -> bt.Subtensor:
|
|
|
20
20
|
"""
|
|
21
21
|
DEFAULT_BITTENSOR_NETWORK = "finney"
|
|
22
22
|
network = getattr(settings, "BITTENSOR_NETWORK", DEFAULT_BITTENSOR_NETWORK)
|
|
23
|
-
logger.info(
|
|
23
|
+
logger.info("Creating new bittensor client for network", network=network)
|
|
24
24
|
return bt.subtensor(network=network)
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
def get_current_celery_task_id() -> str:
|
|
28
|
-
"""
|
|
29
|
-
Get current celery task id
|
|
30
|
-
"""
|
|
28
|
+
"""Get current celery task id."""
|
|
31
29
|
try:
|
|
32
30
|
celery_task_id = current_task.id
|
|
33
31
|
except Exception:
|
|
@@ -36,9 +34,7 @@ def get_current_celery_task_id() -> str:
|
|
|
36
34
|
|
|
37
35
|
|
|
38
36
|
def get_executable_path(func: Callable) -> str:
|
|
39
|
-
"""
|
|
40
|
-
Get executable path for the callable `func`
|
|
41
|
-
"""
|
|
37
|
+
"""Get executable path for the callable `func`."""
|
|
42
38
|
return ".".join([func.__module__, func.__name__])
|
|
43
39
|
|
|
44
40
|
|
{abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/src/abstract_block_dumper/_version.py
RENAMED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.0.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 0,
|
|
31
|
+
__version__ = version = '0.0.2'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 0, 2)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from django.core.management.base import BaseCommand
|
|
2
2
|
|
|
3
|
-
from abstract_block_dumper.dal.memory_registry import task_registry
|
|
4
|
-
from abstract_block_dumper.discovery import ensure_modules_loaded
|
|
5
|
-
from abstract_block_dumper.services.scheduler import task_scheduler_factory
|
|
3
|
+
from abstract_block_dumper._internal.dal.memory_registry import task_registry
|
|
4
|
+
from abstract_block_dumper._internal.discovery import ensure_modules_loaded
|
|
5
|
+
from abstract_block_dumper._internal.services.scheduler import task_scheduler_factory
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class Command(BaseCommand):
|
|
@@ -5,10 +5,10 @@ import structlog
|
|
|
5
5
|
from celery import Task, shared_task
|
|
6
6
|
from django.db import OperationalError, transaction
|
|
7
7
|
|
|
8
|
-
import abstract_block_dumper.dal.django_dal as abd_dal
|
|
9
|
-
import abstract_block_dumper.services.utils as abd_utils
|
|
10
|
-
from abstract_block_dumper.dal.memory_registry import RegistryItem, task_registry
|
|
11
|
-
from abstract_block_dumper.exceptions import
|
|
8
|
+
import abstract_block_dumper._internal.dal.django_dal as abd_dal
|
|
9
|
+
import abstract_block_dumper._internal.services.utils as abd_utils
|
|
10
|
+
from abstract_block_dumper._internal.dal.memory_registry import RegistryItem, task_registry
|
|
11
|
+
from abstract_block_dumper._internal.exceptions import CeleryTaskLockedError
|
|
12
12
|
from abstract_block_dumper.models import TaskAttempt
|
|
13
13
|
|
|
14
14
|
logger = structlog.get_logger(__name__)
|
|
@@ -20,7 +20,6 @@ def schedule_retry(task_attempt: TaskAttempt) -> None:
|
|
|
20
20
|
|
|
21
21
|
Task must already be in FAILED state with next_retry_at set by mark_failed()
|
|
22
22
|
"""
|
|
23
|
-
|
|
24
23
|
if not task_attempt.next_retry_at:
|
|
25
24
|
logger.error(
|
|
26
25
|
"Cannot schedule retry without next_retry_at",
|
|
@@ -79,7 +78,7 @@ def _celery_task_wrapper(func, block_number: int, **kwargs) -> dict[str, Any] |
|
|
|
79
78
|
block_number=block_number,
|
|
80
79
|
executable_path=executable_path,
|
|
81
80
|
)
|
|
82
|
-
raise
|
|
81
|
+
raise CeleryTaskLockedError("TaskAttempt not found - task may have been canceled directly")
|
|
83
82
|
except OperationalError as e:
|
|
84
83
|
logger.info(
|
|
85
84
|
"Task already being processed by another worker",
|
|
@@ -87,7 +86,7 @@ def _celery_task_wrapper(func, block_number: int, **kwargs) -> dict[str, Any] |
|
|
|
87
86
|
executable_path=executable_path,
|
|
88
87
|
operational_error=str(e),
|
|
89
88
|
)
|
|
90
|
-
raise
|
|
89
|
+
raise CeleryTaskLockedError("Task already being processed by another worker")
|
|
91
90
|
|
|
92
91
|
if task_attempt.status != TaskAttempt.Status.PENDING:
|
|
93
92
|
logger.info(
|
|
@@ -146,7 +145,7 @@ def block_task(
|
|
|
146
145
|
celery_kwargs: dict[str, Any] | None = None,
|
|
147
146
|
) -> Callable[..., Any]:
|
|
148
147
|
"""
|
|
149
|
-
|
|
148
|
+
Register a block task.
|
|
150
149
|
|
|
151
150
|
Args:
|
|
152
151
|
condition: Lambda function that determines when to execute
|
|
@@ -14,7 +14,7 @@ from django.utils import timezone
|
|
|
14
14
|
from abstract_block_dumper.models import TaskAttempt
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
@shared_task(name="abstract_block_dumper.cleanup_old_tasks")
|
|
17
|
+
@shared_task(name="abstract_block_dumper.v1.cleanup_old_tasks")
|
|
18
18
|
def cleanup_old_tasks(days: int = 7) -> dict[str, int | str]:
|
|
19
19
|
"""
|
|
20
20
|
Delete all succeeded or unrecoverable failed tasks older than the specified number of days.
|
|
@@ -47,12 +47,12 @@ def cleanup_old_tasks(days: int = 7) -> dict[str, int | str]:
|
|
|
47
47
|
|
|
48
48
|
Example cron (daily at 2 AM):
|
|
49
49
|
0 2 * * * python manage.py shell -c \
|
|
50
|
-
"from abstract_block_dumper.tasks import cleanup_old_tasks; cleanup_old_tasks.delay()"
|
|
50
|
+
"from abstract_block_dumper.v1.tasks import cleanup_old_tasks; cleanup_old_tasks.delay()"
|
|
51
51
|
|
|
52
52
|
Example Celery beat schedule (in settings.py):
|
|
53
53
|
CELERY_BEAT_SCHEDULE = {
|
|
54
54
|
'cleanup-old-tasks': {
|
|
55
|
-
'task': 'abstract_block_dumper.cleanup_old_tasks',
|
|
55
|
+
'task': 'abstract_block_dumper.v1.cleanup_old_tasks',
|
|
56
56
|
'schedule': crontab(hour=2, minute=0), # Daily at 2 AM
|
|
57
57
|
'kwargs': {'days': 7},
|
|
58
58
|
},
|
|
File without changes
|
|
@@ -3,7 +3,7 @@ import pytest
|
|
|
3
3
|
from celery import Celery
|
|
4
4
|
from django.conf import settings
|
|
5
5
|
|
|
6
|
-
from abstract_block_dumper.dal.memory_registry import task_registry
|
|
6
|
+
from abstract_block_dumper._internal.dal.memory_registry import task_registry
|
|
7
7
|
|
|
8
8
|
from .django_fixtures import * # noqa: F401, F403
|
|
9
9
|
|
|
@@ -45,7 +45,7 @@ def failing_task_func(block_number: int):
|
|
|
45
45
|
@pytest.fixture
|
|
46
46
|
def setup_test_tasks():
|
|
47
47
|
# Register test tasks using decorators
|
|
48
|
-
from abstract_block_dumper.decorators import block_task
|
|
48
|
+
from abstract_block_dumper.v1.decorators import block_task
|
|
49
49
|
|
|
50
50
|
# every block
|
|
51
51
|
block_task(condition=lambda bn: True)(every_block_task_func)
|
|
File without changes
|
|
@@ -2,12 +2,12 @@ from unittest.mock import patch
|
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
4
|
|
|
5
|
+
from abstract_block_dumper._internal.services.scheduler import task_scheduler_factory
|
|
5
6
|
from abstract_block_dumper.models import TaskAttempt
|
|
6
|
-
from abstract_block_dumper.services.scheduler import task_scheduler_factory
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
@pytest.mark.django_db
|
|
10
|
-
@patch("abstract_block_dumper.services.utils.get_bittensor_client")
|
|
10
|
+
@patch("abstract_block_dumper._internal.services.utils.get_bittensor_client")
|
|
11
11
|
def test_complete_e2e_workflow(mock_get_bittensor_client, setup_test_tasks) -> None:
|
|
12
12
|
block_number = 300
|
|
13
13
|
mock_subtensor = mock_get_bittensor_client.return_value
|
|
@@ -28,7 +28,7 @@ def test_complete_e2e_workflow(mock_get_bittensor_client, setup_test_tasks) -> N
|
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
@pytest.mark.django_db
|
|
31
|
-
@patch("abstract_block_dumper.services.utils.get_bittensor_client")
|
|
31
|
+
@patch("abstract_block_dumper._internal.services.utils.get_bittensor_client")
|
|
32
32
|
def test_block_processing_flow(mock_get_bittensor_client, setup_test_tasks):
|
|
33
33
|
current_block = 100
|
|
34
34
|
|
|
@@ -6,12 +6,12 @@ import pytest
|
|
|
6
6
|
from celery.result import EagerResult
|
|
7
7
|
from django.conf import settings
|
|
8
8
|
|
|
9
|
-
import abstract_block_dumper.dal.django_dal as abd_dal
|
|
10
|
-
from abstract_block_dumper.dal.memory_registry import task_registry
|
|
11
|
-
from abstract_block_dumper.
|
|
12
|
-
from abstract_block_dumper.
|
|
9
|
+
import abstract_block_dumper._internal.dal.django_dal as abd_dal
|
|
10
|
+
from abstract_block_dumper._internal.dal.memory_registry import task_registry
|
|
11
|
+
from abstract_block_dumper._internal.exceptions import CeleryTaskLockedError
|
|
12
|
+
from abstract_block_dumper._internal.services.utils import get_executable_path
|
|
13
13
|
from abstract_block_dumper.models import TaskAttempt
|
|
14
|
-
from abstract_block_dumper.
|
|
14
|
+
from abstract_block_dumper.v1.decorators import block_task
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
def simple_task(block_number: int) -> str:
|
|
@@ -37,7 +37,7 @@ def test_concurrent_celery_task_call() -> None:
|
|
|
37
37
|
registry_item = task_registry.get_by_executable_path(task.executable_path)
|
|
38
38
|
try:
|
|
39
39
|
output = registry_item.function.delay(task.block_number)
|
|
40
|
-
except
|
|
40
|
+
except CeleryTaskLockedError:
|
|
41
41
|
return None
|
|
42
42
|
return output.result
|
|
43
43
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
|
|
3
|
-
import abstract_block_dumper.dal.django_dal as abd_dal
|
|
4
|
-
from abstract_block_dumper.dal.memory_registry import task_registry
|
|
5
|
-
from abstract_block_dumper.
|
|
3
|
+
import abstract_block_dumper._internal.dal.django_dal as abd_dal
|
|
4
|
+
from abstract_block_dumper._internal.dal.memory_registry import task_registry
|
|
5
|
+
from abstract_block_dumper._internal.services.utils import get_executable_path
|
|
6
6
|
from abstract_block_dumper.models import TaskAttempt
|
|
7
|
-
from abstract_block_dumper.
|
|
7
|
+
from abstract_block_dumper.v1.decorators import block_task
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def multi_arg_task(block_number: int, netuid: int, custom_param: str) -> str:
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
|
|
3
|
-
import abstract_block_dumper.dal.django_dal as abd_dal
|
|
3
|
+
import abstract_block_dumper._internal.dal.django_dal as abd_dal
|
|
4
|
+
import abstract_block_dumper._internal.services.utils as abd_utils
|
|
4
5
|
import abstract_block_dumper.models as abd_models
|
|
5
|
-
|
|
6
|
-
from abstract_block_dumper.
|
|
7
|
-
from abstract_block_dumper.decorators import block_task
|
|
8
|
-
from abstract_block_dumper.services.block_processor import block_processor_factory
|
|
6
|
+
from abstract_block_dumper._internal.dal.memory_registry import task_registry
|
|
7
|
+
from abstract_block_dumper._internal.services.block_processor import block_processor_factory
|
|
8
|
+
from abstract_block_dumper.v1.decorators import block_task
|
|
9
9
|
from tests.conftest import every_block_task_func, failing_task_func
|
|
10
10
|
from tests.fatories import TaskAttemptFactory
|
|
11
11
|
|
{abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/tests/integration/test_scheduler.py
RENAMED
|
@@ -4,12 +4,12 @@ from unittest.mock import patch
|
|
|
4
4
|
import pytest
|
|
5
5
|
from django.utils import timezone
|
|
6
6
|
|
|
7
|
-
import abstract_block_dumper.dal.django_dal as abd_dal
|
|
8
|
-
import abstract_block_dumper.services.utils as abd_utils
|
|
9
|
-
from abstract_block_dumper.dal.memory_registry import task_registry
|
|
10
|
-
from abstract_block_dumper.
|
|
7
|
+
import abstract_block_dumper._internal.dal.django_dal as abd_dal
|
|
8
|
+
import abstract_block_dumper._internal.services.utils as abd_utils
|
|
9
|
+
from abstract_block_dumper._internal.dal.memory_registry import task_registry
|
|
10
|
+
from abstract_block_dumper._internal.services.block_processor import block_processor_factory
|
|
11
11
|
from abstract_block_dumper.models import TaskAttempt
|
|
12
|
-
from abstract_block_dumper.
|
|
12
|
+
from abstract_block_dumper.v1.decorators import block_task
|
|
13
13
|
from tests.fatories import TaskAttemptFactory
|
|
14
14
|
|
|
15
15
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
|
|
3
|
-
import abstract_block_dumper.dal.django_dal as abd_dal
|
|
4
|
-
import abstract_block_dumper.services.utils as abd_utils
|
|
5
|
-
from abstract_block_dumper.dal.memory_registry import task_registry
|
|
6
|
-
from abstract_block_dumper.discovery import ensure_modules_loaded
|
|
3
|
+
import abstract_block_dumper._internal.dal.django_dal as abd_dal
|
|
4
|
+
import abstract_block_dumper._internal.services.utils as abd_utils
|
|
5
|
+
from abstract_block_dumper._internal.dal.memory_registry import task_registry
|
|
6
|
+
from abstract_block_dumper._internal.discovery import ensure_modules_loaded
|
|
7
7
|
from abstract_block_dumper.models import TaskAttempt
|
|
8
8
|
from tests.conftest import every_block_task_func
|
|
9
9
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/block_explorer/admin.py
RENAMED
|
File without changes
|
{abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/block_explorer/apps.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/block_explorer/models.py
RENAMED
|
File without changes
|
{abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/block_explorer/tests.py
RENAMED
|
File without changes
|
{abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/block_explorer/views.py
RENAMED
|
File without changes
|
|
File without changes
|
{abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/example_project/asgi.py
RENAMED
|
File without changes
|
|
File without changes
|
{abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/example_project/urls.py
RENAMED
|
File without changes
|
{abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/example_project/example_project/wsgi.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/src/abstract_block_dumper/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/src/abstract_block_dumper/admin.py
RENAMED
|
File without changes
|
{abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/src/abstract_block_dumper/apps.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstract_block_dumper-0.0.1 → abstract_block_dumper-0.0.2}/src/abstract_block_dumper/py.typed
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|