autopub 0.2.2__py3-none-any.whl → 1.0.0a1__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.
autopub/autopub.py DELETED
@@ -1,83 +0,0 @@
1
- import argparse
2
- import os
3
- import sys
4
-
5
- sys.path.append(os.path.dirname(__file__)) # noqa
6
-
7
- from build_release import build_release
8
- from check_release import check_release
9
- from commit_release import git_commit_and_push
10
- from create_github_release import create_github_release
11
- from deploy_release import deploy_release
12
- from prepare_release import prepare_release
13
- from publish_release import publish_release
14
-
15
-
16
- def check(arguments):
17
- check_release()
18
-
19
-
20
- def prepare(arguments):
21
- prepare_release()
22
-
23
-
24
- def build(arguments):
25
- build_release()
26
-
27
-
28
- def commit(arguments):
29
- git_commit_and_push()
30
-
31
-
32
- def githubrelease(arguments):
33
- create_github_release()
34
-
35
-
36
- def publish(arguments):
37
- publish_release()
38
-
39
-
40
- def deploy(arguments):
41
- deploy_release()
42
-
43
-
44
- def parse_arguments():
45
- try:
46
- version = __import__("pkg_resources").get_distribution("autopub").version
47
- except Exception:
48
- version = "unknown"
49
-
50
- parser = argparse.ArgumentParser()
51
- parser.add_argument("--version", action="version", version=version)
52
-
53
- subparsers = parser.add_subparsers()
54
-
55
- check_parser = subparsers.add_parser("check")
56
- check_parser.set_defaults(func=check)
57
-
58
- prepare_parser = subparsers.add_parser("prepare")
59
- prepare_parser.set_defaults(func=prepare)
60
-
61
- build_parser = subparsers.add_parser("build")
62
- build_parser.set_defaults(func=build)
63
-
64
- commit_parser = subparsers.add_parser("commit")
65
- commit_parser.set_defaults(func=commit)
66
-
67
- githubrelease_parser = subparsers.add_parser("githubrelease")
68
- githubrelease_parser.set_defaults(func=githubrelease)
69
-
70
- publish_parser = subparsers.add_parser("publish")
71
- publish_parser.set_defaults(func=publish)
72
-
73
- deploy_parser = subparsers.add_parser("deploy")
74
- deploy_parser.set_defaults(func=deploy)
75
-
76
- arguments = parser.parse_args()
77
-
78
- return arguments
79
-
80
-
81
- def main():
82
- arguments = parse_arguments()
83
- arguments.func(arguments)
autopub/base.py DELETED
@@ -1,159 +0,0 @@
1
- import os
2
- import re
3
- import subprocess
4
-
5
- from pathlib import Path
6
- from tomlkit import parse
7
-
8
-
9
- def dict_get(_dict, keys, default=None):
10
- """Query nested dictionary with list of keys, returning None if not found."""
11
- for key in keys:
12
- if isinstance(_dict, dict):
13
- _dict = _dict.get(key, default)
14
- else:
15
- return default
16
- return _dict
17
-
18
-
19
- # Determine CI/CD environment
20
-
21
- if os.environ.get("CIRCLECI"):
22
- CI_SYSTEM = "circleci"
23
- CIRCLE_PROJECT_USERNAME = os.environ.get("CIRCLE_PROJECT_USERNAME")
24
- CIRCLE_PROJECT_REPONAME = os.environ.get("CIRCLE_PROJECT_REPONAME")
25
- REPO_SLUG = f"{CIRCLE_PROJECT_USERNAME}/{CIRCLE_PROJECT_REPONAME}"
26
- elif os.environ.get("GITHUB_WORKFLOW"):
27
- CI_SYSTEM = "github"
28
- REPO_SLUG = os.environ.get("GITHUB_REPOSITORY")
29
- elif os.environ.get("TRAVIS"):
30
- CI_SYSTEM = "travis"
31
- REPO_SLUG = os.environ.get("TRAVIS_REPO_SLUG")
32
- else:
33
- CI_SYSTEM = os.environ.get("CI_SYSTEM", None)
34
- REPO_SLUG = os.environ.get("REPO_SLUG", None)
35
-
36
- # Project root and file name configuration
37
-
38
- PROJECT_ROOT = os.environ.get("PROJECT_ROOT")
39
- PYPROJECT_FILE_NAME = os.environ.get("PYPROJECT_FILE_NAME", "pyproject.toml")
40
-
41
- if PROJECT_ROOT:
42
- ROOT = Path(PROJECT_ROOT)
43
- else:
44
- ROOT = Path(
45
- subprocess.check_output(["git", "rev-parse", "--show-toplevel"])
46
- .decode("ascii")
47
- .strip()
48
- )
49
-
50
- PYPROJECT_FILE = ROOT / PYPROJECT_FILE_NAME
51
-
52
- # Retrieve configuration from pyproject file
53
-
54
- if os.path.exists(PYPROJECT_FILE):
55
- config = parse(open(PYPROJECT_FILE).read())
56
- else:
57
- raise SystemExit(f"Could not find pyproject file at: {PYPROJECT_FILE}")
58
-
59
- PROJECT_NAME = dict_get(config, ["tool", "autopub", "project-name"])
60
- if not PROJECT_NAME:
61
- PROJECT_NAME = dict_get(config, ["tool", "poetry", "name"])
62
- if not PROJECT_NAME:
63
- raise SystemExit(
64
- "Could not determine project name. Under the pyproject file's "
65
- '[tool.autopub] header, add:\nproject-name = "YourProjectName"'
66
- )
67
-
68
- RELEASE_FILE_NAME = dict_get(
69
- config, ["tool", "autopub", "release-file"], default="RELEASE.md"
70
- )
71
- RELEASE_FILE = ROOT / RELEASE_FILE_NAME
72
-
73
- CHANGELOG_FILE_NAME = dict_get(
74
- config, ["tool", "autopub", "changelog-file"], default="CHANGELOG.md"
75
- )
76
- CHANGELOG_FILE = ROOT / CHANGELOG_FILE_NAME
77
-
78
- CHANGELOG_HEADER = dict_get(
79
- config, ["tool", "autopub", "changelog-header"], default="========="
80
- )
81
-
82
- VERSION_HEADER = dict_get(config, ["tool", "autopub", "version-header"], default="-")
83
- VERSION_STRINGS = dict_get(config, ["tool", "autopub", "version-strings"], default=[])
84
-
85
- TAG_PREFIX = dict_get(config, ["tool", "autopub", "tag-prefix"], default="")
86
-
87
- PYPI_URL = dict_get(config, ["tool", "autopub", "pypi-url"])
88
-
89
- BUILD_SYSTEM = dict_get(config, ["tool", "autopub", "build-system"])
90
- if not BUILD_SYSTEM:
91
- build_requires = dict_get(config, ["build-system", "requires"])
92
- if "poetry" in build_requires:
93
- BUILD_SYSTEM = "poetry"
94
- elif "setuptools" in build_requires:
95
- BUILD_SYSTEM = "setuptools"
96
-
97
- # Git configuration
98
-
99
- GIT_USERNAME = dict_get(config, ["tool", "autopub", "git-username"])
100
- GIT_EMAIL = dict_get(config, ["tool", "autopub", "git-email"])
101
-
102
- # GitHub
103
-
104
- GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN", None)
105
- APPEND_GITHUB_CONTRIBUTOR = dict_get(
106
- config, ["tool", "autopub", "append-github-contributor"], False
107
- )
108
-
109
-
110
- def run_process(popenargs, encoding="utf-8"):
111
- return subprocess.check_output(popenargs).decode(encoding).strip()
112
-
113
-
114
- def git(popenargs):
115
- # Do not decode ASCII for commit messages so emoji are preserved
116
- return subprocess.check_output(["git", *popenargs])
117
-
118
-
119
- def check_exit_code(popenargs):
120
- return subprocess.call(popenargs, shell=True)
121
-
122
-
123
- def get_project_version():
124
- VERSION_REGEX = re.compile(r"^version\s*=\s*\"(?P<version>\d+\.\d+\.\d+)\"$")
125
-
126
- with open(PYPROJECT_FILE) as f:
127
- for line in f:
128
- match = VERSION_REGEX.match(line)
129
-
130
- if match:
131
- return match.group("version")
132
-
133
- return None
134
-
135
-
136
- def get_release_info():
137
- RELEASE_TYPE_REGEX = re.compile(r"^[Rr]elease [Tt]ype: (major|minor|patch)$")
138
-
139
- with open(RELEASE_FILE, "r") as f:
140
- line = f.readline()
141
- match = RELEASE_TYPE_REGEX.match(line)
142
-
143
- if not match:
144
- raise SystemExit(
145
- "The RELEASE file should start with 'Release type' and "
146
- "specify one of the following values: major, minor, or patch."
147
- )
148
-
149
- type_ = match.group(1)
150
- changelog = "".join([l for l in f.readlines()]).strip()
151
-
152
- return type_, changelog
153
-
154
-
155
- def configure_git():
156
- if not GIT_USERNAME or not GIT_EMAIL:
157
- raise SystemExit("git-username and git-email must be defined in the pyproject file")
158
- git(["config", "user.name", GIT_USERNAME])
159
- git(["config", "user.email", GIT_EMAIL])
autopub/build_release.py DELETED
@@ -1,15 +0,0 @@
1
- import os
2
- import sys
3
-
4
- sys.path.append(os.path.dirname(__file__)) # noqa
5
-
6
- from base import BUILD_SYSTEM, run_process
7
-
8
- if BUILD_SYSTEM == "poetry":
9
- build_cmd = ["poetry", "build"]
10
- else:
11
- build_cmd = ["python", "setup.py", "sdist", "bdist_wheel"]
12
-
13
-
14
- def build_release():
15
- run_process(build_cmd)
autopub/check_release.py DELETED
@@ -1,15 +0,0 @@
1
- import os
2
- import sys
3
-
4
- sys.path.append(os.path.dirname(__file__)) # noqa
5
-
6
- from base import CI_SYSTEM, RELEASE_FILE, run_process
7
-
8
-
9
- def check_release():
10
- if not os.path.exists(RELEASE_FILE):
11
- print("Not releasing a new version because there is no RELEASE file.")
12
- if CI_SYSTEM == "circleci":
13
- run_process(["circleci", "step", "halt"])
14
- elif CI_SYSTEM == "github" or CI_SYSTEM == "travis":
15
- sys.exit(1)
autopub/commit_release.py DELETED
@@ -1,33 +0,0 @@
1
- import os
2
- import sys
3
-
4
- sys.path.append(os.path.dirname(__file__)) # noqa
5
-
6
- from base import (
7
- get_project_version,
8
- git,
9
- configure_git,
10
- PROJECT_NAME,
11
- PYPROJECT_FILE_NAME,
12
- CHANGELOG_FILE_NAME,
13
- RELEASE_FILE_NAME,
14
- VERSION_STRINGS,
15
- )
16
-
17
-
18
- def git_commit_and_push():
19
- configure_git()
20
-
21
- version = get_project_version()
22
-
23
- git(["add", PYPROJECT_FILE_NAME])
24
- git(["add", CHANGELOG_FILE_NAME])
25
-
26
- if VERSION_STRINGS:
27
- for version_file in VERSION_STRINGS:
28
- git(["add", version_file])
29
-
30
- git(["rm", "--cached", RELEASE_FILE_NAME])
31
-
32
- git(["commit", "-m", f"Release {PROJECT_NAME} {version}"])
33
- git(["push", "origin", "HEAD"])
@@ -1,66 +0,0 @@
1
- import os
2
- import sys
3
- import time
4
-
5
- sys.path.append(os.path.dirname(__file__)) # noqa
6
-
7
- from base import (
8
- run_process,
9
- check_exit_code,
10
- get_project_version,
11
- configure_git,
12
- PROJECT_NAME,
13
- REPO_SLUG,
14
- TAG_PREFIX,
15
- get_release_info,
16
- )
17
-
18
-
19
- def create_github_release():
20
- try:
21
- from github_release import gh_release_create, gh_asset_upload
22
- except ModuleNotFoundError:
23
- print("Cannot create GitHub release due to missing dependency: github_release")
24
- sys.exit(1)
25
-
26
- configure_git()
27
- version = get_project_version()
28
- tag = f"{TAG_PREFIX}{version}"
29
-
30
- if not version:
31
- print("Unable to determine the current version")
32
- sys.exit(1)
33
-
34
- tag_exists = (
35
- check_exit_code([f'git show-ref --tags --quiet --verify -- "refs/tags/{tag}"'])
36
- == 0
37
- )
38
-
39
- if not tag_exists:
40
- run_process(["git", "tag", tag])
41
- run_process(["git", "push", "--tags"])
42
-
43
- _, changelog = get_release_info()
44
-
45
- gh_release_create(
46
- REPO_SLUG,
47
- tag,
48
- publish=True,
49
- name=f"{PROJECT_NAME} {version}",
50
- body=changelog,
51
- )
52
-
53
- # give some time to the API to get updated
54
- # not sure if this is the proper way to fix the issue
55
- # ideally the githubrelease package shouldn't need
56
- # to do another API call to get the release since it
57
- # should be returned by the create API.
58
- # anyway, this fix might be good enough for the time being
59
-
60
- time.sleep(2)
61
-
62
- gh_asset_upload(
63
- REPO_SLUG,
64
- tag,
65
- pattern="dist/*",
66
- )
autopub/deploy_release.py DELETED
@@ -1,18 +0,0 @@
1
- import os
2
- import sys
3
-
4
- sys.path.append(os.path.dirname(__file__)) # noqa
5
-
6
- from build_release import build_release
7
- from create_github_release import create_github_release
8
- from commit_release import git_commit_and_push
9
- from prepare_release import prepare_release
10
- from publish_release import publish_release
11
-
12
-
13
- def deploy_release():
14
- prepare_release()
15
- build_release()
16
- git_commit_and_push()
17
- create_github_release()
18
- publish_release()
@@ -1,83 +0,0 @@
1
- import os
2
- import subprocess
3
- import sys
4
-
5
- sys.path.append(os.path.dirname(__file__)) # noqa
6
-
7
- from base import GITHUB_TOKEN, REPO_SLUG, APPEND_GITHUB_CONTRIBUTOR
8
-
9
-
10
- def append_github_contributor(file):
11
- if not APPEND_GITHUB_CONTRIBUTOR:
12
- return
13
-
14
- try:
15
- import httpx
16
- except ModuleNotFoundError:
17
- print("Cannot append the GitHub contributor due to missing dependency: httpx")
18
- sys.exit(1)
19
-
20
- org, repo = REPO_SLUG.split("/")
21
- current_commit = (
22
- subprocess.check_output(["git", "rev-parse", "HEAD"]).decode("ascii").strip()
23
- )
24
-
25
- response = httpx.post(
26
- "https://api.github.com/graphql",
27
- json={
28
- "query": """query Contributor(
29
- $owner: String!
30
- $name: String!
31
- $commit: GitObjectID!
32
- ) {
33
- repository(owner: $owner, name: $name) {
34
- object(oid: $commit) {
35
- __typename
36
- ... on Commit {
37
- associatedPullRequests(first: 1) {
38
- nodes {
39
- number
40
- author {
41
- __typename
42
- login
43
- ... on User {
44
- name
45
- }
46
- }
47
- }
48
- }
49
- }
50
- }
51
- }
52
- }""",
53
- "variables": {"owner": org, "name": repo, "commit": current_commit},
54
- },
55
- headers={
56
- "Content-Type": "application/json",
57
- "Authorization": f"Bearer {GITHUB_TOKEN}",
58
- },
59
- )
60
-
61
- payload = response.json()
62
- commit = payload["data"]["repository"]["object"]
63
-
64
- if not commit:
65
- return
66
-
67
- prs = commit["associatedPullRequests"]["nodes"]
68
-
69
- if not prs:
70
- return
71
-
72
- pr = prs[0]
73
-
74
- pr_number = pr["number"]
75
- pr_author_username = pr["author"]["login"]
76
- pr_author_fullname = pr["author"].get("name", "")
77
-
78
- file.write("\n")
79
- file.write("\n")
80
- file.write(
81
- f"Contributed by [{pr_author_fullname or pr_author_username}](https://github.com/{pr_author_username}) via [PR #{pr_number}](https://github.com/{REPO_SLUG}/pull/{pr_number}/)"
82
- )
83
- file.write("\n")
@@ -1,119 +0,0 @@
1
- import os
2
- import re
3
- import sys
4
-
5
- sys.path.append(os.path.dirname(__file__)) # noqa
6
-
7
- from datetime import datetime
8
-
9
- from base import (
10
- configure_git,
11
- get_release_info,
12
- run_process,
13
- CHANGELOG_FILE,
14
- CHANGELOG_HEADER,
15
- ROOT,
16
- VERSION_HEADER,
17
- VERSION_STRINGS,
18
- )
19
-
20
-
21
- def find_existing_changelog_files():
22
- changelogs = []
23
- changelog_paths = [ROOT, ROOT / "docs"]
24
- changelog_names = ["CHANGELOG", "CHANGES", "HISTORY"]
25
- changelog_extensions = ["", ".md", ".markdown", ".mdown", ".mkd", ".rst", ".txt"]
26
- for path in changelog_paths:
27
- for name in changelog_names:
28
- for ext in changelog_extensions:
29
- changelog = path / f"{name}{ext}"
30
- if changelog.is_file():
31
- changelogs.append(changelog)
32
- if len(changelogs) > 0:
33
- print(f"Specified changelog file not found: {CHANGELOG_FILE}")
34
- print("Maybe set 'changelog-file' setting to discovered existing file:\n")
35
- for changelog in changelogs:
36
- print(f"{changelog}\n")
37
- sys.exit(1)
38
-
39
-
40
- def validate_release():
41
- if not CHANGELOG_FILE.is_file():
42
- find_existing_changelog_files()
43
-
44
- if not os.environ.get("PYPI_PASSWORD"):
45
- print("PYPI_PASSWORD environment variable is not set.")
46
- sys.exit(1)
47
-
48
-
49
- def update_version_strings(file_path, new_version):
50
- version_regex = re.compile(r"(^_*?version_*?\s*=\s*['\"])(\d+\.\d+\.\d+)", re.M)
51
- with open(file_path, "r+") as f:
52
- content = f.read()
53
- f.seek(0)
54
- f.write(
55
- re.sub(
56
- version_regex,
57
- lambda match: "{}{}".format(match.group(1), new_version),
58
- content,
59
- )
60
- )
61
- f.truncate()
62
-
63
-
64
- def prepare_release():
65
- configure_git()
66
- validate_release()
67
-
68
- POETRY_DUMP_VERSION_OUTPUT = re.compile(
69
- r"Bumping version from \d+\.\d+\.\d+ to (?P<version>\d+\.\d+\.\d+)"
70
- )
71
-
72
- release_type, release_changelog = get_release_info()
73
-
74
- output = run_process(["poetry", "version", release_type])
75
- version_match = POETRY_DUMP_VERSION_OUTPUT.match(output)
76
-
77
- if not version_match:
78
- print("Unable to bump the project version using Poetry")
79
- sys.exit(1)
80
-
81
- new_version = version_match.group("version")
82
-
83
- if VERSION_STRINGS:
84
- for version_file in VERSION_STRINGS:
85
- file_path = ROOT / version_file
86
- update_version_strings(file_path, new_version)
87
-
88
- current_date = datetime.utcnow().strftime("%Y-%m-%d")
89
-
90
- old_changelog_data = ""
91
- header = ""
92
-
93
- if not CHANGELOG_FILE.is_file():
94
- with open(CHANGELOG_FILE, "a+") as f:
95
- f.write(f"CHANGELOG\n{CHANGELOG_HEADER}\n\n")
96
-
97
- with open(CHANGELOG_FILE, "r") as f:
98
- lines = f.readlines()
99
-
100
- for index, line in enumerate(lines):
101
- if CHANGELOG_HEADER != line.strip():
102
- continue
103
-
104
- old_changelog_data = lines[index + 1 :]
105
- header = lines[: index + 1]
106
- break
107
-
108
- with open(CHANGELOG_FILE, "w") as f:
109
- f.write("".join(header))
110
-
111
- new_version_header = f"{new_version} - {current_date}"
112
-
113
- f.write(f"\n{new_version_header}\n")
114
- f.write(f"{VERSION_HEADER * len(new_version_header)}\n\n")
115
-
116
- f.write(release_changelog)
117
- f.write("\n")
118
-
119
- f.write("".join(old_changelog_data))
@@ -1,93 +0,0 @@
1
- import os
2
- import re
3
- import sys
4
-
5
- sys.path.append(os.path.dirname(__file__)) # noqa
6
-
7
- from datetime import datetime
8
-
9
- from base import (
10
- configure_git,
11
- get_release_info,
12
- run_process,
13
- CHANGELOG_FILE,
14
- CHANGELOG_HEADER,
15
- ROOT,
16
- VERSION_HEADER,
17
- VERSION_STRINGS,
18
- )
19
-
20
- from github_contributor import append_github_contributor
21
-
22
-
23
- def update_version_strings(file_path, new_version):
24
- version_regex = re.compile(r"(^_*?version_*?\s*=\s*['\"])(\d+\.\d+\.\d+)", re.M)
25
- with open(file_path, "r+") as f:
26
- content = f.read()
27
- f.seek(0)
28
- f.write(
29
- re.sub(
30
- version_regex,
31
- lambda match: "{}{}".format(match.group(1), new_version),
32
- content,
33
- )
34
- )
35
- f.truncate()
36
-
37
-
38
- def prepare_release():
39
- configure_git()
40
-
41
- POETRY_DUMP_VERSION_OUTPUT = re.compile(
42
- r"Bumping version from \d+\.\d+\.\d+ to (?P<version>\d+\.\d+\.\d+)"
43
- )
44
-
45
- type_, release_changelog = get_release_info()
46
-
47
- output = run_process(["poetry", "version", type_])
48
- version_match = POETRY_DUMP_VERSION_OUTPUT.match(output)
49
-
50
- if not version_match:
51
- print("Unable to bump the project version using Poetry")
52
- sys.exit(1)
53
-
54
- new_version = version_match.group("version")
55
-
56
- if VERSION_STRINGS:
57
- for version_file in VERSION_STRINGS:
58
- file_path = ROOT / version_file
59
- update_version_strings(file_path, new_version)
60
-
61
- current_date = datetime.utcnow().strftime("%Y-%m-%d")
62
-
63
- old_changelog_data = ""
64
- header = ""
65
-
66
- if not CHANGELOG_FILE.is_file():
67
- with open(CHANGELOG_FILE, "a+") as f:
68
- f.write(f"CHANGELOG\n{CHANGELOG_HEADER}\n\n")
69
-
70
- with open(CHANGELOG_FILE, "r") as f:
71
- lines = f.readlines()
72
-
73
- for index, line in enumerate(lines):
74
- if CHANGELOG_HEADER != line.strip():
75
- continue
76
-
77
- old_changelog_data = lines[index + 1 :]
78
- header = lines[: index + 1]
79
- break
80
-
81
- with open(CHANGELOG_FILE, "w") as f:
82
- f.write("".join(header))
83
-
84
- new_version_header = f"{new_version} - {current_date}"
85
-
86
- f.write(f"\n{new_version_header}\n")
87
- f.write(f"{VERSION_HEADER * len(new_version_header)}\n\n")
88
-
89
- f.write(release_changelog)
90
- append_github_contributor(f)
91
- f.write("\n")
92
-
93
- f.write("".join(old_changelog_data))