Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: CI

on:
push:
pull_request:

jobs:
test:
runs-on: ubuntu-latest

strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]

steps:
- name: Check out code
uses: actions/checkout@v5

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}

- name: Install uv
run: pip install uv

- name: Sync dependencies
run: uv sync --group dev

- name: Run ruff and pyright
run: uv run ruff format . && uv run ruff check --fix . && uv run pyright

- name: Run tests
run: uv run python3 -m unittest tests
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,5 @@ tmp
temp
node_modules
bower_components

.devcontainer
10 changes: 0 additions & 10 deletions .travis.yml

This file was deleted.

77 changes: 43 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,64 +3,70 @@ pybacklog

Backlog API v2 Client Library for Python

[![Build Status](https://travis-ci.org/netmarkjp/pybacklog.svg?branch=master)](https://travis-ci.org/netmarkjp/pybacklog)
[![CI](https://github.com/netmarkjp/pybacklog/actions/workflows/ci.yml/badge.svg)](https://github.com/netmarkjp/pybacklog/actions/workflows/ci.yml)

# Requirements

- Python 2.7 or Python 3.5+
- Python 3.10+
- requests 2.x

# Install
# Usage: install

```
pip install pybacklog
```

# Usage
# Usage: code

```python
from pybacklog import BacklogClient
import os

client = BacklogClient("your_space_name", "your_api_key")
YOUR_SPACE_NAME = os.getenv("BACKLOG_SPACE_NAME", "")
YOUR_API_KEY = os.getenv("BACKLOG_API_KEY", "")
YOUR_PROJECT = os.getenv("BACKLOG_PROJECT", "")
YOUR_ISSUE_KEY = os.getenv("BACKLOG_ISSUE_KEY", "")

client = BacklogClient(YOUR_SPACE_NAME, YOUR_API_KEY)

# space
space = client.do("GET", "space") # GET /api/v2/space
print(space.get(u"spaceKey"))
space = client.space()
print(space.get("spaceKey"))

# project
projects = client.projects()

# activity
activities = client.project_activities("YOUR_PROJECT", {"activityTypeId[]": [1, 2]})
activities = client.project_activities(YOUR_PROJECT, {"activityTypeId[]": [1, 2]})

# list issue
project_id = client.get_project_id("YOUR_PROJECT")
issues = client.issues({"projectId[]":[project_id], "sort": "dueDate"})
project_id = client.get_project_id(YOUR_PROJECT)
issues = client.issues({"projectId[]": [project_id], "sort": "dueDate"})

# specified issue
issue = client.issue("YOUR_PROJECT-999")
issue = client.issue(YOUR_ISSUE_KEY)

# create issue
project_id = client.get_project_id(project_key)
issue_type_id = client.project_issue_types(project_key)[0][u"id"]
priority_id = client.priorities()[0][u"id"]
project_id = client.get_project_id(YOUR_PROJECT)
issue_type_id = client.project_issue_types(YOUR_PROJECT)[0]["id"]
priority_id = client.priorities()[0]["id"]

client.create_issue(project_id,
u"some summary",
issue_type_id,
priority_id,
{"description": u"a is b and c or d."})
if project_id and issue_type_id and priority_id:
client.create_issue(project_id, "some summary", issue_type_id, priority_id, {"description": "a is b and c or d."})

# add comment
client.add_issue_comment("YOUR_PROJECT-999", u"or ... else e.")
client.add_issue_comment(YOUR_ISSUE_KEY, "or ... else e.")

# top 10 star collector
star_collectors = [(client.user_stars_count(u[u"id"], {"since": "2017-06-01", "until": "2017-06-30"})[u"count"], u[u"name"]) for u in client.users()]
star_collectors = [
(client.user_stars_count(u["id"], {"since": "2017-06-01", "until": "2017-06-30"})["count"], u["name"])
for u in client.users()
]
star_collectors.sort()
star_collectors.reverse()

for i, (c, u) in enumerate(star_collectors[:10]):
print(i+1, c, u)
print(i + 1, c, u)
```

supported operations are `pydoc pybacklog.BacklogClient`
Expand All @@ -74,27 +80,30 @@ Use `do` or let's write code and Pull Request.

```python
from pybacklog import BacklogClient
import os

client = BacklogClient("your_space_name", "your_api_key")
YOUR_SPACE_NAME = os.getenv("BACKLOG_SPACE_NAME", "")
YOUR_API_KEY = os.getenv("BACKLOG_API_KEY", "")
YOUR_PROJECT = os.getenv("BACKLOG_PROJECT", "")

client = BacklogClient(YOUR_SPACE_NAME, YOUR_API_KEY)
space = client.do("GET", "space") # GET /api/v2/space
projects = client.do("GET", "projects",
query_params={"archived": false}
) # GET /api/v2/projects?archived=false
activities = client.do("GET", "projects/{project_id_or_key}/activities",
url_params={"project_id_or_key": "myproj"},
query_params={"activityTypeId[]": [1, 2]}
) # GET /api/v2/projects/myproj/activities?activityTypeIds%5B%5D=1&activityTypeIds%5B%5D=2
projects = client.do("GET", "projects", query_params={"archived": False}) # GET /api/v2/projects?archived=false
activities = client.do(
"GET",
"projects/{project_id_or_key}/activities",
url_params={"project_id_or_key": YOUR_PROJECT},
query_params={"activityTypeId[]": [1, 2]},
) # GET /api/v2/projects/myproj/activities?activityTypeIds%5B%5D=1&activityTypeIds%5B%5D=2
```

see also [Backlog API Overview \| Backlog Developer API \| Nulab](https://developer.nulab-inc.com/docs/backlog/)

# Development

```
pip install -r requirements.txt
pip install -r requirements_dev.txt

PYTHONPATH=. python -m unittest tests
uv sync --group dev
uv run python3 -m unittest tests
```

# License
Expand Down
57 changes: 36 additions & 21 deletions examples/project_activities.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,46 @@
# -*- coding: utf-8 -*-

from typing import List, Tuple

from pybacklog import BacklogClient
import os

_space = os.getenv("BACKLOG_SPACE")
_api_key = os.getenv("BACKLOG_API_KEY")
_project = os.getenv("BACKLOG_PROJECT")
_space = os.getenv("BACKLOG_SPACE", "")
_api_key = os.getenv("BACKLOG_API_KEY", "")
_project = os.getenv("BACKLOG_PROJECT", "")


client = BacklogClient(_space, _api_key)
activities = client.do("GET", "projects/{project_id_or_key}/activities",
url_params={"project_id_or_key": _project},
query_params={"activityTypeId[]": [
1, 2, 3, 14], "count": 100}
)

urls = []
items = []
for activity in activities:
url = client.activity_to_issue_url(activity)
if url in urls:
continue
urls.append(url)

item = (activity.get(u"created"), url,
activity.get(u"content").get(u"summary"))
items.append(item)
activities = client.do(
"GET",
"projects/{project_id_or_key}/activities",
url_params={"project_id_or_key": _project},
query_params={"activityTypeId[]": [1, 2, 3, 14], "count": 100},
)

urls: List[str] = []
items: List[Tuple[str, str, str]] = []
if activities:
for activity in activities:
if not isinstance(activity, dict):
continue

created = activity.get("created", "")

url = client.activity_to_issue_url(activity)
if url in urls:
continue
urls.append(url)

try:
summary = activity["content"]["summary"]
except KeyError:
summary = ""
except TypeError:
summary = ""

item = (created, url, summary)
items.append(item)

for item in items:
print(u"{date}\t{url}\t{summary}".format(date=item[0], url=item[1], summary=item[2]))
print("{date}\t{url}\t{summary}".format(date=item[0], url=item[1], summary=item[2]))
50 changes: 27 additions & 23 deletions examples/project_activities2.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,37 @@
# -*- coding: utf-8 -*-

from typing import List, Tuple

from pybacklog import BacklogClient
import os

_space = os.getenv("BACKLOG_SPACE")
_api_key = os.getenv("BACKLOG_API_KEY")
_project = os.getenv("BACKLOG_PROJECT")
_space = os.getenv("BACKLOG_SPACE", "")
_api_key = os.getenv("BACKLOG_API_KEY", "")
_project = os.getenv("BACKLOG_PROJECT", "")


client = BacklogClient(_space, _api_key)
activities = client.project_activities(
_project,
{"activityTypeId[]": [1, 2, 3, 14], "count": 100})

urls = []
items = []
for activity in activities:
url = client.activity_to_issue_url(activity)
if url in urls:
continue
if "None" in url:
print(activity)
continue
urls.append(url)

item = (activity.get(u"created"), url,
activity.get(u"content").get(u"summary"))
items.append(item)
activities = client.project_activities(_project, {"activityTypeId[]": [1, 2, 3, 14], "count": 100})

urls: List[str] = []
items: List[Tuple[str, str, str]] = []
if activities:
for activity in activities:
url = client.activity_to_issue_url(activity)
if url in urls:
continue
urls.append(url)

created = activity.get("created", "")

try:
summary = activity["content"]["summary"]
except KeyError:
summary = ""
except TypeError:
summary = ""
item = (created, url, summary)
items.append(item)

for item in items:
print(u"{date}\t{url}\t{summary}".format(
date=item[0], url=item[1], summary=item[2]))
print("{date}\t{url}\t{summary}".format(date=item[0], url=item[1], summary=item[2]))
48 changes: 48 additions & 0 deletions examples/readme.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from pybacklog import BacklogClient
import os

YOUR_SPACE_NAME = os.getenv("BACKLOG_SPACE_NAME", "")
YOUR_API_KEY = os.getenv("BACKLOG_API_KEY", "")
YOUR_PROJECT = os.getenv("BACKLOG_PROJECT", "")
YOUR_ISSUE_KEY = os.getenv("BACKLOG_ISSUE_KEY", "")

client = BacklogClient(YOUR_SPACE_NAME, YOUR_API_KEY)

# space
space = client.space()
print(space.get("spaceKey"))

# project
projects = client.projects()

# activity
activities = client.project_activities(YOUR_PROJECT, {"activityTypeId[]": [1, 2]})

# list issue
project_id = client.get_project_id(YOUR_PROJECT)
issues = client.issues({"projectId[]": [project_id], "sort": "dueDate"})

# specified issue
issue = client.issue(YOUR_ISSUE_KEY)

# create issue
project_id = client.get_project_id(YOUR_PROJECT)
issue_type_id = client.project_issue_types(YOUR_PROJECT)[0]["id"]
priority_id = client.priorities()[0]["id"]

if project_id and issue_type_id and priority_id:
client.create_issue(project_id, "some summary", issue_type_id, priority_id, {"description": "a is b and c or d."})

# add comment
client.add_issue_comment(YOUR_ISSUE_KEY, "or ... else e.")

# top 10 star collector
star_collectors = [
(client.user_stars_count(u["id"], {"since": "2017-06-01", "until": "2017-06-30"})["count"], u["name"])
for u in client.users()
]
star_collectors.sort()
star_collectors.reverse()

for i, (c, u) in enumerate(star_collectors[:10]):
print(i + 1, c, u)
16 changes: 16 additions & 0 deletions examples/readme2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from pybacklog import BacklogClient
import os

YOUR_SPACE_NAME = os.getenv("BACKLOG_SPACE_NAME", "")
YOUR_API_KEY = os.getenv("BACKLOG_API_KEY", "")
YOUR_PROJECT = os.getenv("BACKLOG_PROJECT", "")

client = BacklogClient(YOUR_SPACE_NAME, YOUR_API_KEY)
space = client.do("GET", "space") # GET /api/v2/space
projects = client.do("GET", "projects", query_params={"archived": False}) # GET /api/v2/projects?archived=false
activities = client.do(
"GET",
"projects/{project_id_or_key}/activities",
url_params={"project_id_or_key": YOUR_PROJECT},
query_params={"activityTypeId[]": [1, 2]},
) # GET /api/v2/projects/myproj/activities?activityTypeIds%5B%5D=1&activityTypeIds%5B%5D=2
Loading