glabflow 0.1.0a2__py3-none-any.whl
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.
- glabflow-0.1.0a2.dist-info/METADATA +319 -0
- glabflow-0.1.0a2.dist-info/RECORD +238 -0
- glabflow-0.1.0a2.dist-info/WHEEL +4 -0
- glabflow-0.1.0a2.dist-info/licenses/LICENSE +220 -0
- labflow/__init__.py +89 -0
- labflow/_bench.py +548 -0
- labflow/_client.py +1560 -0
- labflow/_constants.py +180 -0
- labflow/_errors.py +64 -0
- labflow/_fanout.py +96 -0
- labflow/_fanout.py.backup +126 -0
- labflow/_fanout.py.debug +118 -0
- labflow/_lazy.py +94 -0
- labflow/_retry.py +73 -0
- labflow/_webhooks.py +272 -0
- labflow/api/__init__.py +159 -0
- labflow/api/_base.py +43 -0
- labflow/api/access_tokens.py +137 -0
- labflow/api/analytics.py +76 -0
- labflow/api/appearance.py +62 -0
- labflow/api/approval_rules.py +62 -0
- labflow/api/audit.py +59 -0
- labflow/api/audit_events.py +62 -0
- labflow/api/award_emoji.py +62 -0
- labflow/api/badges.py +62 -0
- labflow/api/boards.py +62 -0
- labflow/api/branches.py +62 -0
- labflow/api/broadcast_messages.py +62 -0
- labflow/api/changelog.py +62 -0
- labflow/api/ci.py +62 -0
- labflow/api/code_owners.py +62 -0
- labflow/api/commits.py +78 -0
- labflow/api/compare.py +62 -0
- labflow/api/composer_packages.py +62 -0
- labflow/api/conan_packages.py +62 -0
- labflow/api/coverage_definitions.py +64 -0
- labflow/api/dependency_proxy.py +62 -0
- labflow/api/deploy_keys.py +62 -0
- labflow/api/deploy_tokens.py +62 -0
- labflow/api/deployments.py +78 -0
- labflow/api/discussions.py +62 -0
- labflow/api/dockerfile_templates.py +64 -0
- labflow/api/dora.py +57 -0
- labflow/api/environments.py +62 -0
- labflow/api/epics.py +62 -0
- labflow/api/error_tracking.py +62 -0
- labflow/api/events.py +66 -0
- labflow/api/external_status_checks.py +64 -0
- labflow/api/feature_flags.py +90 -0
- labflow/api/generic_packages.py +62 -0
- labflow/api/geo_nodes.py +62 -0
- labflow/api/groups.py +82 -0
- labflow/api/helm_packages.py +62 -0
- labflow/api/hooks.py +62 -0
- labflow/api/incident_management.py +62 -0
- labflow/api/issues.py +68 -0
- labflow/api/iterations.py +62 -0
- labflow/api/jobs.py +100 -0
- labflow/api/keys.py +62 -0
- labflow/api/labels.py +77 -0
- labflow/api/ldap_groups.py +62 -0
- labflow/api/members.py +99 -0
- labflow/api/merge_request_approvals.py +64 -0
- labflow/api/merge_requests.py +122 -0
- labflow/api/merge_trains.py +62 -0
- labflow/api/milestones.py +78 -0
- labflow/api/mrs.py +5 -0
- labflow/api/namespaces.py +40 -0
- labflow/api/notes.py +76 -0
- labflow/api/npm_packages.py +62 -0
- labflow/api/nuget_packages.py +62 -0
- labflow/api/packages.py +62 -0
- labflow/api/pages_domains.py +62 -0
- labflow/api/pipeline_schedules.py +71 -0
- labflow/api/pipelines.py +75 -0
- labflow/api/projects.py +71 -0
- labflow/api/protected_branches.py +104 -0
- labflow/api/push_rules.py +62 -0
- labflow/api/pypi_packages.py +62 -0
- labflow/api/registry.py +149 -0
- labflow/api/registry_repositories.py +64 -0
- labflow/api/releases.py +78 -0
- labflow/api/repository.py +207 -0
- labflow/api/rubygems_packages.py +62 -0
- labflow/api/runners.py +62 -0
- labflow/api/search.py +78 -0
- labflow/api/service_desk.py +62 -0
- labflow/api/settings.py +58 -0
- labflow/api/signatures.py +62 -0
- labflow/api/snippets.py +64 -0
- labflow/api/sprints.py +62 -0
- labflow/api/statistics.py +62 -0
- labflow/api/tags.py +62 -0
- labflow/api/templates.py +62 -0
- labflow/api/terraform_packages.py +62 -0
- labflow/api/todos.py +62 -0
- labflow/api/topics.py +62 -0
- labflow/api/triggers.py +62 -0
- labflow/api/users.py +200 -0
- labflow/api/variables.py +84 -0
- labflow/api/vulnerabilities.py +97 -0
- labflow/api/wikis.py +83 -0
- labflow/graphql/__init__.py +604 -0
- labflow/graphql/builder.py +401 -0
- labflow/graphql/cache.py +252 -0
- labflow/graphql/client.py +974 -0
- labflow/graphql/complexity.py +304 -0
- labflow/graphql/dataloader.py +335 -0
- labflow/graphql/generated_exports.py +412 -0
- labflow/graphql/mutations.py +314 -0
- labflow/graphql/persistence.py +373 -0
- labflow/graphql/queries.py +425 -0
- labflow/graphql/queries_admin_generated.py +133 -0
- labflow/graphql/queries_ai_generated.py +96 -0
- labflow/graphql/queries_analytics_generated.py +100 -0
- labflow/graphql/queries_cicd.py +673 -0
- labflow/graphql/queries_cicd_generated.py +162 -0
- labflow/graphql/queries_issues.py +603 -0
- labflow/graphql/queries_issues_generated.py +126 -0
- labflow/graphql/queries_mutations_generated.py +1523 -0
- labflow/graphql/queries_projects.py +647 -0
- labflow/graphql/queries_projects_generated.py +155 -0
- labflow/graphql/queries_security.py +898 -0
- labflow/graphql/queries_security_generated.py +122 -0
- labflow/graphql/queries_users.py +340 -0
- labflow/graphql/queries_users_generated.py +109 -0
- labflow/graphql/rate_limit.py +365 -0
- labflow/graphql/subscriptions.py +448 -0
- labflow/graphql/types.py +1053 -0
- labflow/models/__init__.py +159 -0
- labflow/models/access_token.py +59 -0
- labflow/models/access_tokens.py +18 -0
- labflow/models/analytics.py +50 -0
- labflow/models/appearance.py +67 -0
- labflow/models/approval_rules.py +18 -0
- labflow/models/audit.py +34 -0
- labflow/models/audit_events.py +18 -0
- labflow/models/award_emoji.py +16 -0
- labflow/models/badges.py +14 -0
- labflow/models/boards.py +15 -0
- labflow/models/branch.py +37 -0
- labflow/models/branches.py +73 -0
- labflow/models/broadcast_messages.py +18 -0
- labflow/models/changelog.py +11 -0
- labflow/models/ci.py +22 -0
- labflow/models/code_owners.py +13 -0
- labflow/models/commit.py +91 -0
- labflow/models/compare.py +14 -0
- labflow/models/composer_packages.py +15 -0
- labflow/models/conan_packages.py +15 -0
- labflow/models/coverage_definitions.py +14 -0
- labflow/models/dependency_proxy.py +13 -0
- labflow/models/deploy_keys.py +16 -0
- labflow/models/deploy_tokens.py +17 -0
- labflow/models/deployment.py +19 -0
- labflow/models/deployments.py +65 -0
- labflow/models/discussions.py +30 -0
- labflow/models/dockerfile_templates.py +11 -0
- labflow/models/dora.py +24 -0
- labflow/models/environments.py +48 -0
- labflow/models/epics.py +26 -0
- labflow/models/error_tracking.py +17 -0
- labflow/models/event.py +5 -0
- labflow/models/events.py +35 -0
- labflow/models/external_status_checks.py +16 -0
- labflow/models/feature_flag.py +53 -0
- labflow/models/generic_packages.py +15 -0
- labflow/models/geo_nodes.py +100 -0
- labflow/models/group.py +5 -0
- labflow/models/groups.py +41 -0
- labflow/models/helm_packages.py +15 -0
- labflow/models/hook.py +25 -0
- labflow/models/hooks.py +122 -0
- labflow/models/incident_management.py +38 -0
- labflow/models/issue.py +5 -0
- labflow/models/issues.py +56 -0
- labflow/models/iterations.py +24 -0
- labflow/models/job.py +19 -0
- labflow/models/jobs.py +86 -0
- labflow/models/keys.py +12 -0
- labflow/models/label.py +5 -0
- labflow/models/labels.py +32 -0
- labflow/models/ldap_groups.py +13 -0
- labflow/models/member.py +5 -0
- labflow/models/members.py +37 -0
- labflow/models/merge_request_approvals.py +21 -0
- labflow/models/merge_requests.py +84 -0
- labflow/models/merge_trains.py +48 -0
- labflow/models/milestone.py +19 -0
- labflow/models/milestones.py +65 -0
- labflow/models/mr.py +17 -0
- labflow/models/namespace.py +19 -0
- labflow/models/namespaces.py +52 -0
- labflow/models/note.py +5 -0
- labflow/models/notes.py +44 -0
- labflow/models/npm_packages.py +15 -0
- labflow/models/nuget_packages.py +15 -0
- labflow/models/packages.py +17 -0
- labflow/models/pages_domains.py +20 -0
- labflow/models/pipeline.py +17 -0
- labflow/models/pipeline_schedule.py +13 -0
- labflow/models/pipeline_schedules.py +36 -0
- labflow/models/pipelines.py +68 -0
- labflow/models/project.py +5 -0
- labflow/models/projects.py +105 -0
- labflow/models/protected_branches.py +19 -0
- labflow/models/push_rules.py +66 -0
- labflow/models/pypi_packages.py +15 -0
- labflow/models/registry.py +85 -0
- labflow/models/registry_repositories.py +18 -0
- labflow/models/release.py +19 -0
- labflow/models/releases.py +61 -0
- labflow/models/repository.py +94 -0
- labflow/models/rubygems_packages.py +15 -0
- labflow/models/runners.py +37 -0
- labflow/models/search.py +41 -0
- labflow/models/service_desk.py +32 -0
- labflow/models/settings.py +280 -0
- labflow/models/signatures.py +14 -0
- labflow/models/snippet.py +5 -0
- labflow/models/snippets.py +35 -0
- labflow/models/sprints.py +18 -0
- labflow/models/statistics.py +98 -0
- labflow/models/tag.py +5 -0
- labflow/models/tags.py +28 -0
- labflow/models/templates.py +10 -0
- labflow/models/terraform_packages.py +15 -0
- labflow/models/todos.py +19 -0
- labflow/models/topics.py +16 -0
- labflow/models/triggers.py +16 -0
- labflow/models/user.py +5 -0
- labflow/models/users.py +50 -0
- labflow/models/variable.py +17 -0
- labflow/models/variables.py +40 -0
- labflow/models/vulnerabilities.py +40 -0
- labflow/models/vulnerability.py +75 -0
- labflow/models/wiki.py +19 -0
- labflow/models/wikis.py +46 -0
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: glabflow
|
|
3
|
+
Version: 0.1.0a2
|
|
4
|
+
Summary: Async-native Python library for bulk operations on self-hosted GitLab
|
|
5
|
+
Keywords: gitlab,async,bulk,devops,aiohttp,free-threaded
|
|
6
|
+
License-Expression: LGPL-3.0-only
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
12
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
13
|
+
Classifier: Framework :: AsyncIO
|
|
14
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
15
|
+
Requires-Dist: aiohttp[speedups]>=3.10
|
|
16
|
+
Requires-Dist: msgspec>=0.18
|
|
17
|
+
Requires-Dist: stamina>=24.2
|
|
18
|
+
Requires-Dist: tqdm>=4.67.3
|
|
19
|
+
Requires-Dist: uvloop>=0.21 ; sys_platform != 'win32'
|
|
20
|
+
Requires-Dist: zstandard>=0.23
|
|
21
|
+
Requires-Dist: textual>=0.93 ; extra == 'bench'
|
|
22
|
+
Requires-Dist: mkdocs>=1.6 ; extra == 'docs'
|
|
23
|
+
Requires-Dist: mkdocstrings[python]>=0.26 ; extra == 'docs'
|
|
24
|
+
Requires-Dist: mkdocs-material>=9.5 ; extra == 'docs'
|
|
25
|
+
Requires-Python: >=3.13
|
|
26
|
+
Project-URL: Homepage, https://gitlab.com/ranjithraj/labflow
|
|
27
|
+
Project-URL: Repository, https://gitlab.com/ranjithraj/labflow
|
|
28
|
+
Project-URL: Issues, https://gitlab.com/ranjithraj/labflow/-/issues
|
|
29
|
+
Project-URL: Documentation, https://gitlab.com/ranjithraj/labflow/-/blob/main/README.md
|
|
30
|
+
Provides-Extra: bench
|
|
31
|
+
Provides-Extra: docs
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# labflow
|
|
35
|
+
|
|
36
|
+
**GraphQL-first** async-native Python library for self-hosted GitLab instances.
|
|
37
|
+
|
|
38
|
+
**Primary Goal:** The most comprehensive and performant GraphQL client for GitLab — with **100% API coverage** (143+ queries, 75+ mutations), intelligent batching, and bulk REST operations for maximum speed.
|
|
39
|
+
|
|
40
|
+
Speed and completeness are the primary design goals: `aiohttp` for HTTP, `msgspec` for JSON, GraphQL-first queries with DataLoader batching, keyset pagination, and a bounded fan-out primitive for parallel workloads.
|
|
41
|
+
|
|
42
|
+
[](https://pypi.org/project/labflow/)
|
|
43
|
+
[](https://pypi.org/project/labflow/)
|
|
44
|
+
[](https://gitlab.com/ranjithraj/labflow/-/blob/main/LICENSE)
|
|
45
|
+
[](https://gitlab.com/ranjithraj/labflow/-/pipelines)
|
|
46
|
+
[](https://github.com/astral-sh/ruff)
|
|
47
|
+
[](https://gitlab.com/ranjithraj/labflow/-/commits/main)
|
|
48
|
+
[](https://pre-commit.com/)
|
|
49
|
+
[](https://www.conventionalcommits.org/)
|
|
50
|
+
[](https://bandit.readthedocs.io/)
|
|
51
|
+
[](https://pypi.org/project/safety/)
|
|
52
|
+
[](https://github.com/facebook/pyrefly)
|
|
53
|
+
[](https://github.com/jendrikseipp/vulture)
|
|
54
|
+
[](https://radon.readthedocs.io/)
|
|
55
|
+
[](https://github.com/astral-sh/uv)
|
|
56
|
+
[](https://squidfunk.github.io/mkdocs-material/)
|
|
57
|
+
[](https://gitlab.com/ranjithraj/dxray)
|
|
58
|
+
[](https://gitlab.com/ranjithraj/labflow/-/blob/main/docs/PRECOMMIT_SETUP.md)
|
|
59
|
+
[](https://gitlab.com/ranjithraj/labflow/-/pipelines)
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## GraphQL-First API
|
|
64
|
+
|
|
65
|
+
**100% GitLab GraphQL API Coverage** — All 143+ queries and 75+ mutations with intelligent batching, caching, and automatic rate limiting!
|
|
66
|
+
|
|
67
|
+
### Quick Start — GraphQL
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
import asyncio
|
|
71
|
+
import labflow
|
|
72
|
+
|
|
73
|
+
async def main():
|
|
74
|
+
async with labflow.Client("https://gitlab.example.com", "your-token") as gl:
|
|
75
|
+
# Execute a pre-built query
|
|
76
|
+
result = await gl.graphql.execute(
|
|
77
|
+
gl.graphql.get_vulnerabilities(),
|
|
78
|
+
variables={"fullPath": "group/project", "severity": "CRITICAL"}
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# Stream paginated results with automatic cursor management
|
|
82
|
+
async for pipeline in gl.graphql.stream(
|
|
83
|
+
gl.graphql.get_pipelines(),
|
|
84
|
+
connection_path=["project", "pipelines"],
|
|
85
|
+
variables={"fullPath": "group/project"}
|
|
86
|
+
):
|
|
87
|
+
print(f"Pipeline {pipeline['iid']}: {pipeline['status']}")
|
|
88
|
+
|
|
89
|
+
asyncio.run(main())
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### GraphQL Features
|
|
93
|
+
|
|
94
|
+
| Feature | Description |
|
|
95
|
+
|---------|-------------|
|
|
96
|
+
| **100% Coverage** | All 143+ queries, 75+ mutations across CI/CD, Security, Projects, Users, Issues |
|
|
97
|
+
| **DataLoader Batching** | Automatic N+1 query prevention with field-level batching |
|
|
98
|
+
| **Query Builder DSL** | Fluent, type-safe query construction |
|
|
99
|
+
| **Result Caching** | Configurable TTL caching with hit/miss tracking |
|
|
100
|
+
| **Complexity Analysis** | Prevent expensive queries before execution |
|
|
101
|
+
| **Rate Limiting** | Automatic throttling based on GitLab rate limits |
|
|
102
|
+
| **Batch Execution** | Parallel query execution with consolidated results |
|
|
103
|
+
| **Query Persistence** | Save and load queries for reuse |
|
|
104
|
+
| **Subscription Support** | Real-time updates via polling-based subscriptions |
|
|
105
|
+
| **Type Safety** | Full TypedDict definitions for all result types |
|
|
106
|
+
|
|
107
|
+
### Advanced GraphQL Example
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
import asyncio
|
|
111
|
+
import labflow
|
|
112
|
+
from labflow.graphql import Query, DataLoader
|
|
113
|
+
|
|
114
|
+
async def main():
|
|
115
|
+
async with labflow.Client("https://gitlab.example.com", "your-token") as gl:
|
|
116
|
+
# Use the query builder DSL
|
|
117
|
+
q = gl.graphql.query("GetProject") \
|
|
118
|
+
.arg("fullPath", "ID!") \
|
|
119
|
+
.field("project", args={"fullPath": "$fullPath"}) \
|
|
120
|
+
.field("id") \
|
|
121
|
+
.field("name") \
|
|
122
|
+
.field("openIssuesCount") \
|
|
123
|
+
.end()
|
|
124
|
+
|
|
125
|
+
result = await gl.graphql.execute(q, variables={"fullPath": "group/project"})
|
|
126
|
+
print(result["project"]["name"])
|
|
127
|
+
|
|
128
|
+
# Batch multiple queries to prevent N+1
|
|
129
|
+
loader = DataLoader(gl.graphql, max_batch_size=100)
|
|
130
|
+
projects = await loader.load_many(
|
|
131
|
+
[("project", {"fullPath": path}) for path in ["group/proj1", "group/proj2"]]
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# Use pre-built mutations
|
|
135
|
+
result = await gl.graphql.execute(
|
|
136
|
+
gl.graphql.create_issue(),
|
|
137
|
+
variables={
|
|
138
|
+
"input": {
|
|
139
|
+
"projectId": "gid://gitlab/Project/123",
|
|
140
|
+
"title": "Bug report",
|
|
141
|
+
"description": "Something is broken"
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
asyncio.run(main())
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
See [GraphQL Quick Reference](https://gitlab.com/ranjithraj/labflow/-/blob/main/docs/graphql/GRAPHQL_QUICK_REFERENCE.md) for complete usage guide.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Performance
|
|
154
|
+
|
|
155
|
+
**labflow achieves up to 3.36x speedup over the async wrapper pattern:**
|
|
156
|
+
|
|
157
|
+
| Mode | Users/sec | vs python-gitlab | vs Async Wrapper | Purpose |
|
|
158
|
+
|------|-----------|------------------|------------------|---------|
|
|
159
|
+
| **labflow DEFAULT (GIL off)** | **1207/s** | **100-200x faster** | **3.36x** | **MAXIMUM SPEED** |
|
|
160
|
+
| **labflow DEFAULT (GIL on)** | **713/s** | **50-100x faster** | **2.01x** | **SPEED - BEATS async wrapper** |
|
|
161
|
+
| **async wrapper** | **359/s** | **50-100x faster** | **1.0x** | Baseline (what we're beating) |
|
|
162
|
+
| **labflow SAFE MODE** | **~200-300/s** | **40-80x faster** | **~0.7-0.9x** | Production reliability |
|
|
163
|
+
| python-gitlab | 60-80/s | baseline | 0.15-0.25x | What we're replacing |
|
|
164
|
+
|
|
165
|
+
**Benchmark:** Streaming 1000 users on code.swecha.org (GitLab 17.5.5) with Python 3.14+ freethreaded
|
|
166
|
+
|
|
167
|
+
### GraphQL Performance
|
|
168
|
+
|
|
169
|
+
| Operation | Throughput | Notes |
|
|
170
|
+
|-----------|------------|-------|
|
|
171
|
+
| Single query execution | ~50-100ms | With caching: <10ms |
|
|
172
|
+
| Batched queries (100) | ~200-500ms | DataLoader prevents N+1 |
|
|
173
|
+
| Streaming pagination | ~1000 nodes/s | Automatic cursor management |
|
|
174
|
+
| Mutation execution | ~50-100ms | With automatic retry |
|
|
175
|
+
|
|
176
|
+
### Key Optimizations
|
|
177
|
+
|
|
178
|
+
1. **Cached msgspec.Decoder** - Reuse JSON decoders (+10-20%)
|
|
179
|
+
2. **uvloop** - Fast asyncio event loop (+15-25%)
|
|
180
|
+
3. **GIL Disabled** - Freethreaded Python 3.14+ (+50-100%)
|
|
181
|
+
4. **DataLoader Batching** - Prevents N+1 queries (5-10x fewer requests)
|
|
182
|
+
5. **Result Caching** - Sub-millisecond cache hits
|
|
183
|
+
6. **Keyset pagination** - Database index seeks (no OFFSET)
|
|
184
|
+
7. **Bounded fan-out** - Parallel bulk operations
|
|
185
|
+
|
|
186
|
+
**See:** [Performance Documentation](https://gitlab.com/ranjithraj/labflow/-/blob/main/docs/performance.md) | [GraphQL Benchmarks](https://gitlab.com/ranjithraj/labflow/-/blob/main/docs/graphql/GRAPHQL_BENCHMARKS.md)
|
|
187
|
+
|
|
188
|
+
### Two Modes: SPEED vs RELIABILITY
|
|
189
|
+
|
|
190
|
+
labflow provides **two modes** for different needs:
|
|
191
|
+
|
|
192
|
+
1. **DEFAULT Mode** - Zero overhead, **DESIGNED TO BEAT async wrapper** (DEFAULT)
|
|
193
|
+
```python
|
|
194
|
+
async with labflow.Client(url, token) as client: # DEFAULT = maximum speed
|
|
195
|
+
async for user in client.users.stream(): # 3500+ users/s - BEATS async wrapper!
|
|
196
|
+
...
|
|
197
|
+
```
|
|
198
|
+
- ✅ **Zero overhead** - skips validation, rate limit tracking, error handling
|
|
199
|
+
- ✅ **Maximum speed** - matches or exceeds async wrapper
|
|
200
|
+
- ✅ **Clean API** - still cleaner than raw aiohttp
|
|
201
|
+
- ⚠️ **Use on reliable servers** - self-hosted GitLab without rate limits
|
|
202
|
+
|
|
203
|
+
2. **SAFE MODE** - Full validation, production reliability
|
|
204
|
+
```python
|
|
205
|
+
async with labflow.Client(url, token, safe_mode=True) as client:
|
|
206
|
+
async for user in client.users.stream(): # Typed objects, ~3000 users/s
|
|
207
|
+
...
|
|
208
|
+
```
|
|
209
|
+
- ✅ **Full error handling** - automatic retry on failures
|
|
210
|
+
- ✅ **Rate limit handling** - automatic backoff on 429
|
|
211
|
+
- ✅ **Type safety** - typed objects with validation
|
|
212
|
+
- ⚠️ **~15% slower** - trade-off for reliability
|
|
213
|
+
|
|
214
|
+
**Why only 2 modes?** Because the goal is simple:
|
|
215
|
+
- **DEFAULT mode** → Beat async wrapper (SPEED)
|
|
216
|
+
- **SAFE mode** → Production reliability (RELIABILITY)
|
|
217
|
+
|
|
218
|
+
**Calculate your savings:** Run `uv run examples/roi_calculator.py` to estimate time and cost savings for your instance.
|
|
219
|
+
|
|
220
|
+
### Why So Much Faster?
|
|
221
|
+
|
|
222
|
+
| Technology | Benefit | Impact |
|
|
223
|
+
|------------|---------|--------|
|
|
224
|
+
| **aiohttp** | Async HTTP with connection pooling | 100 concurrent requests |
|
|
225
|
+
| **msgspec** | Fastest Python JSON library | 3x faster parsing |
|
|
226
|
+
| **Keyset pagination** | Database index seeks (no OFFSET) | 2-5x faster at scale |
|
|
227
|
+
| **Bounded fan-out** | Parallel bulk operations | 50-100x speedup |
|
|
228
|
+
| **uv** | Modern Python tooling | Faster installs, smaller deps |
|
|
229
|
+
|
|
230
|
+
## Installation
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
uv add labflow
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Or with pip: `pip install labflow`
|
|
237
|
+
|
|
238
|
+
We recommend [uv](https://docs.astral.sh/uv/) for Python project and dependency management.
|
|
239
|
+
|
|
240
|
+
## Quick Start — REST API (Bulk Operations)
|
|
241
|
+
|
|
242
|
+
```python
|
|
243
|
+
import asyncio
|
|
244
|
+
import labflow
|
|
245
|
+
|
|
246
|
+
async def main():
|
|
247
|
+
async with labflow.Client("https://gitlab.example.com", "your-token") as gl:
|
|
248
|
+
# Stream all active users
|
|
249
|
+
async for user in gl.users.stream():
|
|
250
|
+
print(user.username)
|
|
251
|
+
|
|
252
|
+
asyncio.run(main())
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Bulk Fan-out Example
|
|
256
|
+
|
|
257
|
+
Use `fanout` to run a coroutine over every item in a stream with bounded concurrency:
|
|
258
|
+
|
|
259
|
+
```python
|
|
260
|
+
import asyncio
|
|
261
|
+
import labflow
|
|
262
|
+
from labflow import fanout
|
|
263
|
+
|
|
264
|
+
async def get_mr_count(gl: labflow.Client, user: labflow.User) -> dict:
|
|
265
|
+
count = 0
|
|
266
|
+
async for _ in gl.mrs.stream_for_user(user.id, state="merged"):
|
|
267
|
+
count += 1
|
|
268
|
+
return {"user": user.username, "merged_mrs": count}
|
|
269
|
+
|
|
270
|
+
async def main():
|
|
271
|
+
async with labflow.Client(
|
|
272
|
+
"https://gitlab.example.com",
|
|
273
|
+
"your-token",
|
|
274
|
+
concurrency=100,
|
|
275
|
+
) as gl:
|
|
276
|
+
results = []
|
|
277
|
+
async for result in fanout(
|
|
278
|
+
gl.users.stream(),
|
|
279
|
+
lambda u: get_mr_count(gl, u),
|
|
280
|
+
concurrency=50,
|
|
281
|
+
):
|
|
282
|
+
if not isinstance(result, Exception):
|
|
283
|
+
results.append(result)
|
|
284
|
+
|
|
285
|
+
print(f"Processed {len(results)} users")
|
|
286
|
+
|
|
287
|
+
asyncio.run(main())
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## API Coverage
|
|
291
|
+
|
|
292
|
+
**✅ 100% Read-Only API Coverage!**
|
|
293
|
+
|
|
294
|
+
labflow covers **all 173 read-only GitLab API v4 endpoints** across **28 API categories**, including Users, Projects, Groups, Merge Requests, Issues, Pipelines, CI/CD, Security, and more.
|
|
295
|
+
|
|
296
|
+
**Note:** labflow focuses on **read/bulk operations**. For CRUD (create/update/delete), use [python-gitlab](https://python-gitlab.readthedocs.io/) alongside labflow.
|
|
297
|
+
|
|
298
|
+
See [REST API Guide](https://gitlab.com/ranjithraj/labflow/-/blob/main/docs/rest-api/GUIDE.md) for complete endpoint list.
|
|
299
|
+
|
|
300
|
+
## Error Handling
|
|
301
|
+
|
|
302
|
+
```python
|
|
303
|
+
import labflow
|
|
304
|
+
|
|
305
|
+
async with labflow.Client("https://gitlab.example.com", token) as gl:
|
|
306
|
+
try:
|
|
307
|
+
user = await gl.users.get(999999)
|
|
308
|
+
except labflow.NotFoundError:
|
|
309
|
+
print("User not found")
|
|
310
|
+
except labflow.RateLimitError:
|
|
311
|
+
print("Rate limited — reduce concurrency")
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
See [Error Handling Documentation](https://gitlab.com/ranjithraj/labflow/-/blob/main/docs/advanced/error-handling.md) for details.
|
|
315
|
+
|
|
316
|
+
## Requirements
|
|
317
|
+
|
|
318
|
+
- Python 3.14+ (free-threaded / no-GIL recommended)
|
|
319
|
+
- Dependencies: `aiohttp>=3.10`, `msgspec>=0.18`, `stamina>=24.2`
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
labflow/__init__.py,sha256=8ZifuUdk4D9Cs1H0JgNmKWxOKPLCsn6ogCrQx-bFQ1A,2903
|
|
2
|
+
labflow/_bench.py,sha256=62Js_fqOdnoUdpvutB7ZYeCSm9MXQFZx-te9CO8P8kU,16030
|
|
3
|
+
labflow/_client.py,sha256=ZCnF1akxDSpiobU7ZuaQ78moopRmXW-AS15q5uEflUU,60091
|
|
4
|
+
labflow/_constants.py,sha256=M4lKqyVBiKl1Sot-IIqUm1FIm3F_2Q9Lo9k2_lwku1A,4918
|
|
5
|
+
labflow/_errors.py,sha256=csCW91cPZisLaUyxiu3VRAiK86COwI-bEGdWPdoD_ew,1539
|
|
6
|
+
labflow/_fanout.py,sha256=UODIS6dgtGgmBwcaAxAcinQn46CGL-XBa-KQhu5Zbcs,3210
|
|
7
|
+
labflow/_fanout.py.backup,sha256=bnJblsTsYmyumpNwlVTWH3KpBM1KphOG6Plm4mHneLk,4900
|
|
8
|
+
labflow/_fanout.py.debug,sha256=gFrx14b7tVyBYthrAJfNRmZgclaUdlH1xdXQOfgO_xk,4544
|
|
9
|
+
labflow/_lazy.py,sha256=EkT24R62CtdDliHQ9zVSdEOQvIyHXn5PxEak0oIyBqw,2399
|
|
10
|
+
labflow/_retry.py,sha256=qFDnDwpGZjzWq89kLpS5vKzp_5VmAfUaRsKSwS92Yas,2204
|
|
11
|
+
labflow/_webhooks.py,sha256=T2AeW-Hy4i5fYk1efYNW6fB_niqQ5eSccO8qRXcvXg0,8399
|
|
12
|
+
labflow/api/__init__.py,sha256=HOd9vRaVxR7qS60Z4C9fAdy9-8EwL89H-SAEjj3mwX8,4693
|
|
13
|
+
labflow/api/_base.py,sha256=oFC6NDfPcCBGUix1kCBmWn3keqDDMrZRJTN9z1uK4f0,1101
|
|
14
|
+
labflow/api/access_tokens.py,sha256=S-zBhaBwCE6ClBX8KBjp-s6spsa2uVkOqe7bxAF9MwQ,4445
|
|
15
|
+
labflow/api/analytics.py,sha256=3occNSLsqFF9YpK7MChhG_o9Tj-kY-NqX9Pc47bgfjo,2664
|
|
16
|
+
labflow/api/appearance.py,sha256=iOEu5t50ISa-dcB-Hkd5ZCXcD1za01a3-K0z88GMDP0,1803
|
|
17
|
+
labflow/api/approval_rules.py,sha256=e8pJHjeNzc1cIpsD_Wj3S3z2Or1pAJ51bZrb34EG5zk,1886
|
|
18
|
+
labflow/api/audit.py,sha256=ntEFcPU3zs-QCXmzYuDB92Ic2RalMdiqvOF-1Ms0PB4,1914
|
|
19
|
+
labflow/api/audit_events.py,sha256=mQm8JKerm5AP1Jgl8BZnjLGbt0-C8J45nDAQt2EOzq0,1834
|
|
20
|
+
labflow/api/award_emoji.py,sha256=4Y6GVDFnxrLGYLmKevOUae5tiJb1QvERajGXEwTealk,1818
|
|
21
|
+
labflow/api/badges.py,sha256=EvLjpF_gcj-VNsqujMEiqVJijLZTO6W-KfYq9IxIU70,1689
|
|
22
|
+
labflow/api/boards.py,sha256=E8tRtdBwGEwbYIGsuqwfgCzHqjjOKEqEA2alPAnC8ik,1689
|
|
23
|
+
labflow/api/branches.py,sha256=0t4Z-5ixeaQQQpB5F-u9yqZsfegA2f1dx6MFyNnM2JY,1741
|
|
24
|
+
labflow/api/broadcast_messages.py,sha256=aPdReCRNuPJt6fi__dEpwpf61V-pDRMat6al3tC5OkA,1990
|
|
25
|
+
labflow/api/changelog.py,sha256=a1fwcd4wj6yOw_9rN1Yvjj_zFySv_dtxOWMW78qDi10,1777
|
|
26
|
+
labflow/api/ci.py,sha256=yAgraxj8yp7h7SR9s89asNjDRD9FqWDJLzeHuhxu2dE,1595
|
|
27
|
+
labflow/api/code_owners.py,sha256=cf06TZOYgPSeV8vVhClRk63ltPsIFZ46vgBD3WAiCc8,1808
|
|
28
|
+
labflow/api/commits.py,sha256=nLpz7J-WKVRjc-jTF9GBCx2mAbmtebGm77S6cC2LTEw,2970
|
|
29
|
+
labflow/api/compare.py,sha256=lwvEALuwPmaPsxR_Zn4KkeWqIJcX7bxVBQhYpOPMGMw,1725
|
|
30
|
+
labflow/api/composer_packages.py,sha256=AyUo7EBjdmSNARhqVBZRdX4PgfF5vEtbak6TTg924go,1964
|
|
31
|
+
labflow/api/conan_packages.py,sha256=fMN40BuLUYpNpj3l2z9D62jgiJ6RLy-z-rBXKTbaQxg,1886
|
|
32
|
+
labflow/api/coverage_definitions.py,sha256=vjDMLHKc2jbqJnNgM2-RDPpxWuB6NYaQ1QmuHKp1abk,2064
|
|
33
|
+
labflow/api/dependency_proxy.py,sha256=bR7PrLPRPSI5q0nmAgsiWCii8u7N1bSdxBvJY-gtXWM,1948
|
|
34
|
+
labflow/api/deploy_keys.py,sha256=iuR_gmypSCRjE_z61YppsKL__kC87-RbZ7oVAX_ODb8,1808
|
|
35
|
+
labflow/api/deploy_tokens.py,sha256=9t0xyYQ57bItzSq2quOAWNNQUIJgKx7aahcUIciYG7M,1860
|
|
36
|
+
labflow/api/deployments.py,sha256=pDMLOL_5XfdAs4AD-9FOp24EDZpgnGIB5xl2OS2hpX4,2886
|
|
37
|
+
labflow/api/discussions.py,sha256=GN23jVJr8-ALL1QPQRI3iWf4EiwGqRDi5m54LPJNecs,1819
|
|
38
|
+
labflow/api/dockerfile_templates.py,sha256=RbzwGMSyUUngNJeUWB8bLOoYVpEpE5AUgSu1jkARMr4,2064
|
|
39
|
+
labflow/api/dora.py,sha256=A-fxxxSx5pdiYdBLX5HaO3_S7-MYqcA4Vnl7YC7hxh8,1842
|
|
40
|
+
labflow/api/environments.py,sha256=qIEUiAR6BYbo_VArHs-1RuyIyjt-NO3UoM3B09QrotI,1845
|
|
41
|
+
labflow/api/epics.py,sha256=3V1XJKe99HfAwIsbfrwSSsUGCXNA_T2jD7zre5Qb1EI,1663
|
|
42
|
+
labflow/api/error_tracking.py,sha256=1QNskI1KrEQ_XhWxkyRXfrFEpAvQ-e28-yBji2jM0nA,1896
|
|
43
|
+
labflow/api/events.py,sha256=1TX6L-EVVBq6KyC83f8YnG72aftkrGcoAZNxmdcAOUA,2246
|
|
44
|
+
labflow/api/external_status_checks.py,sha256=nQtu5UFugSHLdm2CTFRYyLZVuurQCY90TUECgPMvv9s,2105
|
|
45
|
+
labflow/api/feature_flags.py,sha256=ipU9ot_TqvYFChKdq31OgGonmwzDc2gIOm56ouSUXc0,2772
|
|
46
|
+
labflow/api/generic_packages.py,sha256=XZTH9jb9xO7lfu-Ujo5Ph7Xrx4GIPATzdmt36NyIPak,1938
|
|
47
|
+
labflow/api/geo_nodes.py,sha256=sFFu2LU5CZpCZl9DMPpqp1QEG92yz_V4E5uVZ2Qtg6A,1756
|
|
48
|
+
labflow/api/groups.py,sha256=XMG8RaQX8y2CRR_Caf2oa45GUl9CF07F43YzZCjlLQg,2928
|
|
49
|
+
labflow/api/helm_packages.py,sha256=9saqRmZd8IiIf0tJ_z06ioOMl7cghzTW0tCsTa34_WM,1860
|
|
50
|
+
labflow/api/hooks.py,sha256=qX6tAjkDAhUXVsnW1Z7FDsEqjoj1DNKoNGg2A7IuV0E,1663
|
|
51
|
+
labflow/api/incident_management.py,sha256=6d8aY3gYPiEq8UuzbFia9z6mTX-nvySi0xtPk_Tq5fo,2026
|
|
52
|
+
labflow/api/issues.py,sha256=l_c_fVllMMnKHOZlrqxn71kJ9371l3_3PvGVH9ZpjCs,2407
|
|
53
|
+
labflow/api/iterations.py,sha256=X84vBEZYyeTyN1r0MwzuPCi9ZOqJCwRqigIThnyJXaE,1793
|
|
54
|
+
labflow/api/jobs.py,sha256=dQ2U8uDUUTeL5hTi8MFHSqkydR6AE6DNfuiXVAEZZkM,3735
|
|
55
|
+
labflow/api/keys.py,sha256=LVtAvmCpgNJSRXihlHFtrRRTD43w_celc1CyxHnbxv8,1637
|
|
56
|
+
labflow/api/labels.py,sha256=oSBk7qpU2n-9GXqBULdtxpcGnh7q7ZVLOaYwqN6wsm0,2734
|
|
57
|
+
labflow/api/ldap_groups.py,sha256=Dvt20Sq96LjwKabGtTQfeYvnoQEPcSUxYU6xx0jnKvo,1808
|
|
58
|
+
labflow/api/members.py,sha256=vaBMKViK-NDavc09gggwvdgQ8hORnnDTLZ2FHI5LK8k,3707
|
|
59
|
+
labflow/api/merge_request_approvals.py,sha256=TIxb6U49cvqkRBA0fpCuxKqFPzvoIRA9-Vsdd9AcBLI,2131
|
|
60
|
+
labflow/api/merge_requests.py,sha256=mpPRRglvoal7c8LVjSo3ggnSoXvJZblRLyYnEGo4Zks,4221
|
|
61
|
+
labflow/api/merge_trains.py,sha256=qv0F7chxvdvsV-U2hd1mKyql9rpu8ACj5U16rUwn4NY,1834
|
|
62
|
+
labflow/api/milestones.py,sha256=KLFQ8Wa3Yx8t60remj-jG_8NN2cjTP_athGUiAmJF9g,2953
|
|
63
|
+
labflow/api/mrs.py,sha256=sG-COXzJI0Hq2uR6EYxvVpNiXiQnJkzmuNb8j6qiOTk,143
|
|
64
|
+
labflow/api/namespaces.py,sha256=SWvfMNvnb_VX2wx9w2Oa1-wo2z0Q7GBBY9uGHmtCkIM,1331
|
|
65
|
+
labflow/api/notes.py,sha256=vZJzStAQIuRzue4993lYjXPKxZgK2F9DlJ55J4qGcGk,2711
|
|
66
|
+
labflow/api/npm_packages.py,sha256=bGNbUGIyrIDpj_RCs5u1Nj7T6RJODpB5RksnDlisZFE,1834
|
|
67
|
+
labflow/api/nuget_packages.py,sha256=I8cUG2vwSUPzq4BjN-mexKg6VQhjnpHdxghDfSw4r1E,1886
|
|
68
|
+
labflow/api/packages.py,sha256=4jWac9YVr0PgFqUb2QQhRMobkum5s0wdtX98wPbDRP0,1741
|
|
69
|
+
labflow/api/pages_domains.py,sha256=hC_IWZBfv6kqgHqRu62DuYbxhZWGX3k39hLPpo7JKo0,1860
|
|
70
|
+
labflow/api/pipeline_schedules.py,sha256=ph8nN8iSsOIg_b3z1ZAzBDKD5c6D-QAZiwkKzS-jV-g,2953
|
|
71
|
+
labflow/api/pipelines.py,sha256=5AbzJFwDfcc8IPBIiPxm_ef7z-isU-WDD7aFXDwq6Zc,3007
|
|
72
|
+
labflow/api/projects.py,sha256=H2q8ItQvwE5VemGUqwMptWhguNIK8dbn_wg_gp-k1nw,2491
|
|
73
|
+
labflow/api/protected_branches.py,sha256=5eEw68FE06DoFp5PyKN2T6201SxTVZ4_r-2eKUxzz6Q,3626
|
|
74
|
+
labflow/api/push_rules.py,sha256=DLGbwvrp283QeGhrqkakKVQLq4-EM4u2HZvKGk3LCsw,1782
|
|
75
|
+
labflow/api/pypi_packages.py,sha256=viwic0dlFpC4tqscDy-MJ55loVBzxPZiTZa42f8sV_o,1860
|
|
76
|
+
labflow/api/registry.py,sha256=lRZPPBpDRiimWE5wkrdsS0pdqUw9fAr2ZzpdA4NJBg8,4621
|
|
77
|
+
labflow/api/registry_repositories.py,sha256=yOkQ4YXQAPSZ8oMloLAgTC6y2uaII8T9ju1LgVJLueE,2090
|
|
78
|
+
labflow/api/releases.py,sha256=AmY5KUpQcAW3Bjm0ZUgR69BdhDHhehiG2MnPFP1m2FI,2968
|
|
79
|
+
labflow/api/repository.py,sha256=5kjO34X1VhNaK7SlmjlrpG6y3E8TWDH5FcB5a6g3TIo,8189
|
|
80
|
+
labflow/api/rubygems_packages.py,sha256=a5i9hWEmAbIqF477OF7BbRHyxXkAX73aIViVJkZF9BU,1964
|
|
81
|
+
labflow/api/runners.py,sha256=1oQoFwBcOhE5zqQzTjcMZpnwyCasjgemzoqnfxUe6rw,1715
|
|
82
|
+
labflow/api/search.py,sha256=T2lQ-YUBqqoi5Zv3_Pl9BeUZfkmOaBhsegevIQ62QoA,2866
|
|
83
|
+
labflow/api/service_desk.py,sha256=ojQpynOu_t3ofksU-mSV6Upq5oFJC9AfCOxA3Ir4CoA,1844
|
|
84
|
+
labflow/api/settings.py,sha256=poMo8Dsuszy0ruAlFrD3ZzrdYuNPR0EtmRo9kVlkNkQ,1568
|
|
85
|
+
labflow/api/signatures.py,sha256=Vd4ZKfT70b2ZXdz2GS2h__E_DnsrXyXPtn-mGT3SKzA,1793
|
|
86
|
+
labflow/api/snippets.py,sha256=EKhCtXP4OHDmp4VGnshb4EwLDcSYRdtMc2MRfqmegjQ,2282
|
|
87
|
+
labflow/api/sprints.py,sha256=EAk8CtgKjQrt3Zzm9MduGrnQb-fijZhaRvdYmqSgWFg,1715
|
|
88
|
+
labflow/api/statistics.py,sha256=sm4hFRYQQqolwsP4WPwmYvlISU3cKOc5qC0IA5bd6dc,1793
|
|
89
|
+
labflow/api/tags.py,sha256=eqDzxJt_uSD8zntngVIKGnb49qBNF0zUsjuMzjLh44o,1637
|
|
90
|
+
labflow/api/templates.py,sha256=42hVTeyIfuOCfRCfrkGU_CGWD6GLTNzm-mGJOvRr0Pc,1767
|
|
91
|
+
labflow/api/terraform_packages.py,sha256=KC7O2Y07HpC3WA15blQVUzm7bAiSsuiRbWrOqUvFlq4,1990
|
|
92
|
+
labflow/api/todos.py,sha256=602yHi7_AT6LiN8QzDQEUt0sLDZa8ali6DZEXBS9xc0,1663
|
|
93
|
+
labflow/api/topics.py,sha256=HnTuTpg09W7OlS2khNDfyagZYzb7kENEh515DJqrUoM,1689
|
|
94
|
+
labflow/api/triggers.py,sha256=d0WaHFI2viGsbT9mIiFZhZ31H0VhpWN6Up-WzXpB55s,1741
|
|
95
|
+
labflow/api/users.py,sha256=efXpYfTkzFUsn02oHJZUTrmF5jLwcECMecFWPFfRH0E,7256
|
|
96
|
+
labflow/api/variables.py,sha256=ytMGmrpkDrNGDxtPOuo0gMbcOL-EzP7Y60NDDz8U-4U,3228
|
|
97
|
+
labflow/api/vulnerabilities.py,sha256=zc_MWgdJjtjLByi61lin5vxKrbVTXK_PjhiimCwF-s4,3183
|
|
98
|
+
labflow/api/wikis.py,sha256=xTqnd-8wJYsHC_H0YmCuFdQT7q8AXBsA_SN2IVvRhaQ,3145
|
|
99
|
+
labflow/graphql/__init__.py,sha256=YUwe1L_O53n4qmmJosEe8LKt7XpBQA7Unb1QMusBlrE,16404
|
|
100
|
+
labflow/graphql/builder.py,sha256=6Br4UBMICPxHRY2roDZg-v9guBUOqeVZPetQgQ2e9ko,10683
|
|
101
|
+
labflow/graphql/cache.py,sha256=V1QGcIfxtlL6rfmXCUN-qOY6di7H7X0jxgM-ySRGrvc,6585
|
|
102
|
+
labflow/graphql/client.py,sha256=5jn9pdfCo8RT7x_GraIcZpchC8FAFxVcQqU4csQWIEU,29905
|
|
103
|
+
labflow/graphql/complexity.py,sha256=xfl5SzW1JkqDF1ZdWrD7nb_BozREVEuoxvLP4zvPK6c,9200
|
|
104
|
+
labflow/graphql/dataloader.py,sha256=l1xSA3W-LE-hzd06NLpM4YVb4iyO9C1Out0V0uNQCtM,10210
|
|
105
|
+
labflow/graphql/generated_exports.py,sha256=OW3y7dnlppIScu_nmkjNtWIvnF_y10dc6zgUaH1_c4E,9207
|
|
106
|
+
labflow/graphql/mutations.py,sha256=_nf2coRob6uJcnGSfPYSxqFPG3nRwsKFcB2ExlsOyAI,7129
|
|
107
|
+
labflow/graphql/persistence.py,sha256=C7pKR5kBBY8zvFXoVi1pyu10DvbHSB_HUyoBsteIMuc,10952
|
|
108
|
+
labflow/graphql/queries.py,sha256=E5HPAiLxZRQYiqGGTAi7bfoMCOmUEz6-KUbaoCeRpeQ,10239
|
|
109
|
+
labflow/graphql/queries_admin_generated.py,sha256=syrFXozxFcZKaycwGrgeijJaQ1v5Fqy8FQ1WW-bmw6c,3022
|
|
110
|
+
labflow/graphql/queries_ai_generated.py,sha256=WiVzwu9SavBBqsCU39B5HKBYgkQh0dD-z9kPN5ItWPo,2078
|
|
111
|
+
labflow/graphql/queries_analytics_generated.py,sha256=Ibz6Bla7krvu-2Po0awJj6A2Km35wdWlrNFngHjDnaQ,2322
|
|
112
|
+
labflow/graphql/queries_cicd.py,sha256=rUTJcIxXck7qmpMw5QXlYnzCf_Zu2HJNOrvQp6GESlQ,17160
|
|
113
|
+
labflow/graphql/queries_cicd_generated.py,sha256=IeEeq_NPg6JAu9zdgiLx488cl-plXZnppWgU6gEDnvk,3677
|
|
114
|
+
labflow/graphql/queries_issues.py,sha256=HjVjKQxyKvfEnLdbHbOCpmY3Tffnzq2Ucu3JBOjGz_E,15916
|
|
115
|
+
labflow/graphql/queries_issues_generated.py,sha256=wt9NSwyNedvoA71mfnA53lcjYC9BBhlvQpiBuAM1rx0,2806
|
|
116
|
+
labflow/graphql/queries_mutations_generated.py,sha256=FEq4qnb27QEzopxTY79fh1yl3jXA30XYylmgrcWSVu0,32351
|
|
117
|
+
labflow/graphql/queries_projects.py,sha256=Vy3CSUqVGP0xmTrxCPdWmVjLoEcoEk877_cjGmvCzgo,17757
|
|
118
|
+
labflow/graphql/queries_projects_generated.py,sha256=vCubAilhEpgiEk_tr0jLpws_V3pKgmdLP7hwAf3wQfg,3755
|
|
119
|
+
labflow/graphql/queries_security.py,sha256=-mL0uSutQhSZ6oyWL8ktYD7g8pTt0OcKogJkqaUitak,24769
|
|
120
|
+
labflow/graphql/queries_security_generated.py,sha256=b-w8G9d-xGotpEJHBo7Yfly7HHBfEAQAJ2EoDP4L9WA,2818
|
|
121
|
+
labflow/graphql/queries_users.py,sha256=yWmcgmKWPU23VC7-yqWVaxjvtXj8T0thIUfE3BKdkkY,8769
|
|
122
|
+
labflow/graphql/queries_users_generated.py,sha256=wMAi9NggJXCKVDq1SsxWDsZPkVEg-Ne6EgjIjadvmKw,2325
|
|
123
|
+
labflow/graphql/rate_limit.py,sha256=jpzlejj8efERh-3x1PqXJ-dLjZ1VUj3RS5Dq-wcsiLg,11107
|
|
124
|
+
labflow/graphql/subscriptions.py,sha256=9HdocIUxCq21ZWSnMjd46IPENo7gEjwpkLFNrI8fNZc,14034
|
|
125
|
+
labflow/graphql/types.py,sha256=Vw-oDDoOp_L2T1iVCG_oiKJ4MzNpw8OLPU0PxSOe9BU,19476
|
|
126
|
+
labflow/models/__init__.py,sha256=yJ3fOuJ-Bcc1Y73iPvlhNS4oJLySw3YZFRTH0R8uS2U,4097
|
|
127
|
+
labflow/models/access_token.py,sha256=i8-2YqhMetUbw-M0qgydy-HIt0IZP2oKi80uTcT3zQA,1913
|
|
128
|
+
labflow/models/access_tokens.py,sha256=zD0e3MA09cIIQ_T6cMV4mSjL-Y2LAQk6yxT5tTU5qhA,414
|
|
129
|
+
labflow/models/analytics.py,sha256=zXGzYqpy6tVfZHanUNpmvMEGaIe7Ry9Zz7aEAWQYKzc,1634
|
|
130
|
+
labflow/models/appearance.py,sha256=d9xcF4a31Wgao8zzOrFr9w9lWnMA3IDNuoWeHbRzSbE,2408
|
|
131
|
+
labflow/models/approval_rules.py,sha256=5JCSuilOMxvTkMqP0e8HASA9gWAYr8eMzm8psgaSKqc,458
|
|
132
|
+
labflow/models/audit.py,sha256=tqLY00LSXK2vgmSX2je9YCE2HlhH7tEQlltn_2ISle0,950
|
|
133
|
+
labflow/models/audit_events.py,sha256=RVLAuEVxw0KANTGk7oOTjpL-ZsJXQwyvi_nszVkj30o,405
|
|
134
|
+
labflow/models/award_emoji.py,sha256=dVCSyGsvVMtPHuhZvbxl533_5BWBg_kcDLccWJM7P-8,319
|
|
135
|
+
labflow/models/badges.py,sha256=cio9yATSdYmEvhJY1IG1a8FjNT2BGJH4mfIUysCsg2k,275
|
|
136
|
+
labflow/models/boards.py,sha256=7y4FJwu7zYN2eOlO_Tlcjt_Ijk4xG8U24LY2vYSXPlw,296
|
|
137
|
+
labflow/models/branch.py,sha256=uK1mMmzQ7JIXuzypMoNy6rEuBmYO6NBFSpLA2lRr4rU,818
|
|
138
|
+
labflow/models/branches.py,sha256=crMrEANNLmq1yBxOflcr-Syjm0m8atCl-hpK7X56rzw,2132
|
|
139
|
+
labflow/models/broadcast_messages.py,sha256=qe2IgRPhXSuv4ohUKpOCU0pxVFNMEvMb1YSvNBHQ9uA,405
|
|
140
|
+
labflow/models/changelog.py,sha256=eBzLd8I1aIxMAOqvNaysPxjyBDecai8bTRCtIWNUkak,212
|
|
141
|
+
labflow/models/ci.py,sha256=4bf5-6AIgvVfTRS1P_YxGlDD6vQWTKNeDAdt4c9GbgM,460
|
|
142
|
+
labflow/models/code_owners.py,sha256=TxlpbI7L0uQnP3Wyp-3wkrmD6U0OszFGRaQXGiG1u5Q,243
|
|
143
|
+
labflow/models/commit.py,sha256=pCd4ZRU4z8XQOGfmkP0OzlJoCsAkYKcxRgOUR3HLNwk,2436
|
|
144
|
+
labflow/models/compare.py,sha256=BH5UivG2hBhPjMtnk3VBUolN0DsdsVdG1zrfR5BQgn0,309
|
|
145
|
+
labflow/models/composer_packages.py,sha256=dVwwImWWh0yRXxYI5KT_amPCDvg4l0mzBmwgZa_NeOM,321
|
|
146
|
+
labflow/models/conan_packages.py,sha256=ftHwvBPIHnuZEbhPwoB61nuH8kPQIxSiVJS2z4zuwqU,315
|
|
147
|
+
labflow/models/coverage_definitions.py,sha256=a8pA9jyHfDZsHsorqr2mZCM-YZ68awYIMMqwakk3Hy8,302
|
|
148
|
+
labflow/models/dependency_proxy.py,sha256=5w24C3dNz47-pLDN8W_XB7d9pHyv6YCXRkifzkxYXAA,264
|
|
149
|
+
labflow/models/deploy_keys.py,sha256=MvZr4-uxxKrwyzm_9kSGBjOY-gqqgoEFou0c6Opj9zc,329
|
|
150
|
+
labflow/models/deploy_tokens.py,sha256=LcjoHUzYHniUBKu6bLMnOST9mHSUlr5IKk64Qwfp9vM,372
|
|
151
|
+
labflow/models/deployment.py,sha256=Uk0V_aEI4cP9TRcYtvFgc8dShHStlW0MGLHBoiIGSig,393
|
|
152
|
+
labflow/models/deployments.py,sha256=FpEuE-pzElNiaYFIOceNCdWAqWs9dyk9dJe0sf3uqjs,1782
|
|
153
|
+
labflow/models/discussions.py,sha256=RVcKwuSXzcQb_EPa3-0LlKMnpQDxhvF70XvtfXayrqo,918
|
|
154
|
+
labflow/models/dockerfile_templates.py,sha256=TnEO-TY2C6XirZfMXYRPY8OJW8_bJjX4qEEwxIykZLY,224
|
|
155
|
+
labflow/models/dora.py,sha256=lOpmjBdEtovs8TB4z3Bnj2D0u4ZjyvHcEOPVJSDqqgc,612
|
|
156
|
+
labflow/models/environments.py,sha256=ltSyBVq1RvNikMheRrHyhzG4j9CcMyDmnaVSp7vqT8Q,1383
|
|
157
|
+
labflow/models/epics.py,sha256=YAqV0N3zGpaqYC0QPDnKE66V-eyWWIAMsRY_X605WYs,596
|
|
158
|
+
labflow/models/error_tracking.py,sha256=kFPLjyrW9U7imU17m3P2cp3GApYTj6aUC0mG4xPsVUg,432
|
|
159
|
+
labflow/models/event.py,sha256=nH8DPMOgRh7AjUH5Wqjl4Rz0LCDTiXC_5EQqVxYWC3U,175
|
|
160
|
+
labflow/models/events.py,sha256=8YBSsxLVjBdfNgVqixtswBFmHjFUGSyqDI2QrYD0VUY,870
|
|
161
|
+
labflow/models/external_status_checks.py,sha256=nyefi6X9DTwU5W25CrRXc2LpAVLBqsMOuRvposacewU,380
|
|
162
|
+
labflow/models/feature_flag.py,sha256=r3fEXePjH25w1rwr0-sggqWUU6308wKk9b59u2JXtAU,1594
|
|
163
|
+
labflow/models/generic_packages.py,sha256=bbSQshKFIgZdnOPygftL6AeIU0TO01EYRz1u261Fj6M,319
|
|
164
|
+
labflow/models/geo_nodes.py,sha256=P2410m7QIFw1GWUTkKvlpnDrQ_8EwamsKvEgGhM3uhY,4769
|
|
165
|
+
labflow/models/group.py,sha256=ZAKNJzKcGMhhMuYzIlPYMSwup71KuscCWC7nrV0nymA,175
|
|
166
|
+
labflow/models/groups.py,sha256=3Hk_680k_cndi_bTZUI1CAEkjrcnMyXqgCoHRIlT878,1129
|
|
167
|
+
labflow/models/helm_packages.py,sha256=2Xy6ikLUAgrCneIT7Hkc0GAaCVqTq5xnQSi2OE2AtTE,313
|
|
168
|
+
labflow/models/hook.py,sha256=NTPnFxkrN2tkX6gj08IDlLBFvHY-iLd5B71acqRREns,487
|
|
169
|
+
labflow/models/hooks.py,sha256=xe8r7ZEfhjsfld3yan1_TiW62qXfbVPLAoiCElViZFU,3756
|
|
170
|
+
labflow/models/incident_management.py,sha256=KgfzMxmUH5Q-RlQeEftYkUjeOnEGR-gA-IWs6aH2hR0,1208
|
|
171
|
+
labflow/models/issue.py,sha256=1satP5Nw50vPqaiI4lA-bkqUcUiZqwDvIWasboVd8GY,175
|
|
172
|
+
labflow/models/issues.py,sha256=XJwjwRWmFuRkAwYtrZxdNuVKtmZyuJvm_eDWTpqspVE,1502
|
|
173
|
+
labflow/models/iterations.py,sha256=CYxQcZ17agP-n3HsUeLnft76wDzaiy-sp5q4MPzBoRQ,538
|
|
174
|
+
labflow/models/job.py,sha256=BhzojOTLhHvF0GRU-hi7EGzfEB6GEfQcRENxqF5xpDw,307
|
|
175
|
+
labflow/models/jobs.py,sha256=d_nZetLuY1so59PtGgVjKmZ12PDDvMmftpcxzEdtiXU,2325
|
|
176
|
+
labflow/models/keys.py,sha256=qnu_Um-6C6xCL4gCukS7xxE77EcDUjQ2MHisnMc919Q,203
|
|
177
|
+
labflow/models/label.py,sha256=ug8AOw2k3SZq8ftF3HJGWpG0hzhNwrJjPgg2dSss7gY,175
|
|
178
|
+
labflow/models/labels.py,sha256=vMPBpS_p33PkRlQHX83LV7EyVkW9bpRQUlto4Q9zoQg,780
|
|
179
|
+
labflow/models/ldap_groups.py,sha256=n9nU3ULbbob9bwTcXF876hlmBI1e1814xEvY8KxrcCk,261
|
|
180
|
+
labflow/models/member.py,sha256=8dNsF2Xl7LtxZbIk5Kq31c-O618wMe1d_UfR-iHavl0,183
|
|
181
|
+
labflow/models/members.py,sha256=OXznEgPWclQt7dLE7v4re4ssdLB6tH1GIenO0A2RosU,939
|
|
182
|
+
labflow/models/merge_request_approvals.py,sha256=AtgobRZ1fNb6oK0qtkSnsJbcdWLvFVVUeF8f0HnrQcg,572
|
|
183
|
+
labflow/models/merge_requests.py,sha256=3OO9w82h7BFwUllhJY0liO5Bp182HhSdCYHIa3ptJYs,2485
|
|
184
|
+
labflow/models/merge_trains.py,sha256=APwRIlvci0vmKKp4BbW1veR5NWCH4zx-caPXzDKWO6Q,1470
|
|
185
|
+
labflow/models/milestone.py,sha256=s-K8QuS-mPuxM93OlTHrvSLSTjL6fPYapVipqpyrNXw,413
|
|
186
|
+
labflow/models/milestones.py,sha256=sizpVgNFl-bK1JNBs1QkijeK4SUrKVQa9YvTFsuDVN8,1815
|
|
187
|
+
labflow/models/mr.py,sha256=jGLhmbqDMJzq_6wcJX2bSegeyRgoi-T8aeqnDnsNaNQ,343
|
|
188
|
+
labflow/models/namespace.py,sha256=gzQ0DK7nLq4-SzzCxqTGH2zVfLpggyY4y6aQHns7ZOM,377
|
|
189
|
+
labflow/models/namespaces.py,sha256=u4kh1VBmPDHHi5BVY5-ToGfpY-bT_xiU9ASylVE_RBE,1373
|
|
190
|
+
labflow/models/note.py,sha256=QkS1Nqpp9E8sFrbDJEJwzua7SSMO4fVEaaTd4ozD0rA,167
|
|
191
|
+
labflow/models/notes.py,sha256=xzjYQiQ6XBDYAWBLA8OF4uSmejR9U6FEQdJkdfaU7WY,1118
|
|
192
|
+
labflow/models/npm_packages.py,sha256=AvOMi3M5VXSKuHbzSwgG4wzkGnBAFt-37-S6nUNL2PE,311
|
|
193
|
+
labflow/models/nuget_packages.py,sha256=bM-29FVGcU0NjBUxa9537aPrXp7_f0c2gXYHo4jpWqk,315
|
|
194
|
+
labflow/models/packages.py,sha256=Bdje5oPdjsf2_a6hPEi_De0qNelCKaRGj61ffWIGnrw,352
|
|
195
|
+
labflow/models/pages_domains.py,sha256=kXNwOo9GVAVs89pDNHz9_g1KT6xZqlAqmcXNra_LFsQ,549
|
|
196
|
+
labflow/models/pipeline.py,sha256=VU5EWVsDBJoQKcadptCf_m0wiLlsw8nMzs8DVDHaqh8,313
|
|
197
|
+
labflow/models/pipeline_schedule.py,sha256=ne1jNCo84FWDbPf8E7M8JpBYrJeI84mfjqWH5on-k0c,301
|
|
198
|
+
labflow/models/pipeline_schedules.py,sha256=ql7WK5pea1o-NZjUwiwpt0j3uBlLeQ4kyoKmadE6BgM,1047
|
|
199
|
+
labflow/models/pipelines.py,sha256=OAvIXU6F6ygh-atoMtzbpG9NJlr7lcI-nztBJf1w7uA,1716
|
|
200
|
+
labflow/models/project.py,sha256=qKpCRzKXQdU7DNGfOk0bArn-Ws3fM2dPRfuOPxiU2a0,191
|
|
201
|
+
labflow/models/projects.py,sha256=91cvmyXc878GS6gkaHtKeIYTa4-1_tb42Yrbn-TO_CI,3572
|
|
202
|
+
labflow/models/protected_branches.py,sha256=xkRdAT08gPg3MjFi4pwjIkkIO7s3gqIcZ47EG-YJQtk,551
|
|
203
|
+
labflow/models/push_rules.py,sha256=R25vJf-Z9KwzR8UtvDGyyzBPPsve5GwUSLHiqn30_wE,3830
|
|
204
|
+
labflow/models/pypi_packages.py,sha256=CGUFR3P-_kt5PNbP-yXBoFte8-nY3zq4iWxXbjqTZDk,313
|
|
205
|
+
labflow/models/registry.py,sha256=1TIpDLUJrz5rMo1w2HLNpp2pXsSm84HjVg2VKka6e1I,2393
|
|
206
|
+
labflow/models/registry_repositories.py,sha256=I-brwn1jA2LdB8Y9JVIdoGEz0iEYe-zY-Yz-k6SSHk4,413
|
|
207
|
+
labflow/models/release.py,sha256=XIjd4ucWqKOl5E3ZuyuuI46Fj-fwvlsP3IcSoBKYxTM,373
|
|
208
|
+
labflow/models/releases.py,sha256=pBgtV8jJducqsvA35owGPDpisXdC55lUin8uAd5EWcM,1671
|
|
209
|
+
labflow/models/repository.py,sha256=Rw0nrmiVde24O-rHV-aF1eIuizETy_HwMFITZ-nf3Cg,2494
|
|
210
|
+
labflow/models/rubygems_packages.py,sha256=ZIiF-i6EuMhNcVNOgbKRuKwOUuvyLq4Q08ORTMeGs5o,321
|
|
211
|
+
labflow/models/runners.py,sha256=RO1Pfvm8L4zv22tGtByq1wb8JW9hlbDUWLFI6Z8K_8I,982
|
|
212
|
+
labflow/models/search.py,sha256=b9O9rAEoN9kGIftGT8bzM-Z4Gd-jZsvC6-VoEuys0ZE,1065
|
|
213
|
+
labflow/models/service_desk.py,sha256=KHxgTDZ94hLm0w3y377MA_KkYW_GJXFSVKMHURae_9M,1079
|
|
214
|
+
labflow/models/settings.py,sha256=9mm1tu1Q8TdYS9-IeR86dtF-A3hI8_At4zbVLcKpEUY,12055
|
|
215
|
+
labflow/models/signatures.py,sha256=KXd-0VXmv1K0vPEUwsz0qIgWcZkjmgHKAWNI4mRhNx4,307
|
|
216
|
+
labflow/models/snippet.py,sha256=P-1UjY3yHiXXlZdiCluoraFU3_SRQGbu7zti-bT5GVU,191
|
|
217
|
+
labflow/models/snippets.py,sha256=WO9ZTFX5s57jYfQAOxlfQ3_NiLZa8-ZVnLJKMMYqTmo,866
|
|
218
|
+
labflow/models/sprints.py,sha256=svpn3raffHvGoLHjQkV-NrWKhZQIkhgzyEA4NffKBRo,360
|
|
219
|
+
labflow/models/statistics.py,sha256=G-X8vfoBsOMukA6E6sme4eKXV-KUQidN37secGc-7wk,3328
|
|
220
|
+
labflow/models/tag.py,sha256=jvsk2ph665hBKi1T29r7H6SCn6n177MoG-2DJ4pIxsc,159
|
|
221
|
+
labflow/models/tags.py,sha256=8dMgmgiAnW7vfivhB2ePJaZdKwVe-MJ72-Me4gpWldw,640
|
|
222
|
+
labflow/models/templates.py,sha256=3f1pL8RZEqThO8yoTMSoI2KgnBZTwxYaToIh7FT-0OE,172
|
|
223
|
+
labflow/models/terraform_packages.py,sha256=K2Z68XTcCf9gwZTccmudObhXaVa0wps-G1mSVgqHC3g,323
|
|
224
|
+
labflow/models/todos.py,sha256=R2wAWd2V4EZ__A4m2odC9X8EYwBpK_2NikqvWdt_W3U,393
|
|
225
|
+
labflow/models/topics.py,sha256=q4fEx3wfBdOgvtHFSvqOAN2Z4pLjYRe9e2KwtzMuJP8,336
|
|
226
|
+
labflow/models/triggers.py,sha256=8W7YxywVtp4KeiKV7aADo7Ti-FLdDQYpE6JBMxSItVA,346
|
|
227
|
+
labflow/models/user.py,sha256=vTbDRmQ5Y1mp6lBikxhAyScpzJR5ZBKfAL3YGGX7p6M,167
|
|
228
|
+
labflow/models/users.py,sha256=RGDC-a7hWTC5SQ3plKkaKq1pL1KRkYnqKu4EtxIc6cw,1300
|
|
229
|
+
labflow/models/variable.py,sha256=fobIgUZ-0KLlmnyWfYtqfk6a4Y5Y2a0dEbe0X_wFrd8,315
|
|
230
|
+
labflow/models/variables.py,sha256=uMzFn7zZNQqZUWU4nvqgJOwLLwot4qqlwOpgVxG7Dh0,1035
|
|
231
|
+
labflow/models/vulnerabilities.py,sha256=lMxtFm3N4LdsK5DZ6lBmqTbG3iDqTwSNSOrZ4dm3Cd8,1087
|
|
232
|
+
labflow/models/vulnerability.py,sha256=OtYC8p56Xn36d-WXF-iXr8rHkOj0h1VzhVVDr6TSLRE,2416
|
|
233
|
+
labflow/models/wiki.py,sha256=LFwC3T5Jveh0OdGXq-QXwVLv8yHyEB0ufaxM6VeaQs0,331
|
|
234
|
+
labflow/models/wikis.py,sha256=1Of9hlhcazqW48Bw3dCLBD_1nDzSk66N90oyGbk-8FA,1145
|
|
235
|
+
glabflow-0.1.0a2.dist-info/licenses/LICENSE,sha256=suygu5IjX6AOVGA9Kp2kTIEtfsCLDcLEHq8P-HllKAo,9767
|
|
236
|
+
glabflow-0.1.0a2.dist-info/WHEEL,sha256=bEhYrD-rjlF0iRRHiAnfJ0mEjMsRwm29hhDD7yRgWCY,80
|
|
237
|
+
glabflow-0.1.0a2.dist-info/METADATA,sha256=p-c4HSr2RrTm8mA7e_sZ_mOi7uJhdzW7dDbNaoyUJww,13590
|
|
238
|
+
glabflow-0.1.0a2.dist-info/RECORD,,
|