developers-chamber 0.1.39__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.
Files changed (41) hide show
  1. developers_chamber/__init__.py +0 -0
  2. developers_chamber/bin/__init__.py +0 -0
  3. developers_chamber/bin/pydev.py +92 -0
  4. developers_chamber/bitbucket_utils.py +94 -0
  5. developers_chamber/click/__init__.py +0 -0
  6. developers_chamber/click/alias.py +130 -0
  7. developers_chamber/click/options.py +86 -0
  8. developers_chamber/docker_utils.py +15 -0
  9. developers_chamber/ecs_utils.py +838 -0
  10. developers_chamber/git_utils.py +242 -0
  11. developers_chamber/gitlab_utils.py +94 -0
  12. developers_chamber/jira_utils.py +113 -0
  13. developers_chamber/project_utils.py +355 -0
  14. developers_chamber/qa/__init__.py +0 -0
  15. developers_chamber/qa/base.py +142 -0
  16. developers_chamber/qa/checks.py +217 -0
  17. developers_chamber/scripts/__init__.py +49 -0
  18. developers_chamber/scripts/bitbucket.py +75 -0
  19. developers_chamber/scripts/docker.py +64 -0
  20. developers_chamber/scripts/ecs.py +593 -0
  21. developers_chamber/scripts/git.py +254 -0
  22. developers_chamber/scripts/gitlab.py +297 -0
  23. developers_chamber/scripts/init_aliasses.py +15 -0
  24. developers_chamber/scripts/jira.py +209 -0
  25. developers_chamber/scripts/project.py +846 -0
  26. developers_chamber/scripts/qa.py +93 -0
  27. developers_chamber/scripts/sh.py +15 -0
  28. developers_chamber/scripts/slack.py +49 -0
  29. developers_chamber/scripts/toggle.py +194 -0
  30. developers_chamber/scripts/version.py +120 -0
  31. developers_chamber/slack_utils.py +52 -0
  32. developers_chamber/toggle_utils.py +150 -0
  33. developers_chamber/types.py +64 -0
  34. developers_chamber/utils.py +153 -0
  35. developers_chamber/version_utils.py +194 -0
  36. developers_chamber-0.1.39.dist-info/METADATA +46 -0
  37. developers_chamber-0.1.39.dist-info/RECORD +41 -0
  38. developers_chamber-0.1.39.dist-info/WHEEL +5 -0
  39. developers_chamber-0.1.39.dist-info/entry_points.txt +2 -0
  40. developers_chamber-0.1.39.dist-info/licenses/LICENSE +21 -0
  41. developers_chamber-0.1.39.dist-info/top_level.txt +1 -0
File without changes
File without changes
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env python
2
+ import logging.config
3
+ import os
4
+ import sys
5
+ from pathlib import Path
6
+ from importlib.machinery import SourceFileLoader
7
+
8
+ import click_completion
9
+ import coloredlogs
10
+ from dotenv import load_dotenv
11
+ from developers_chamber.utils import INSTALLED_MODULES
12
+
13
+ for config_path in (Path.home(), Path.cwd()):
14
+ if (config_path / ".pydev").exists() and (config_path / ".pydev").is_dir():
15
+ for file in (config_path / ".pydev").iterdir():
16
+ if (
17
+ file.is_file()
18
+ and file.suffix == ".conf"
19
+ and not file.name.startswith("~")
20
+ ):
21
+ load_dotenv(dotenv_path=str(file), override=True)
22
+
23
+
24
+ from developers_chamber.scripts import cli
25
+
26
+ if "bitbucket" in INSTALLED_MODULES:
27
+ from developers_chamber.scripts.bitbucket import *
28
+ from developers_chamber.scripts.docker import *
29
+
30
+ if "aws" in INSTALLED_MODULES:
31
+ from developers_chamber.scripts.ecs import *
32
+
33
+ if "git" in INSTALLED_MODULES:
34
+ from developers_chamber.scripts.git import *
35
+
36
+ from developers_chamber.scripts.gitlab import *
37
+
38
+ if "jira" in INSTALLED_MODULES:
39
+ from developers_chamber.scripts.jira import *
40
+
41
+ if "qa" in INSTALLED_MODULES:
42
+ from developers_chamber.scripts.qa import *
43
+
44
+ from developers_chamber.scripts.sh import *
45
+
46
+ if "slack" in INSTALLED_MODULES:
47
+ from developers_chamber.scripts.slack import *
48
+
49
+ if "toggle" in INSTALLED_MODULES:
50
+ from developers_chamber.scripts.toggle import *
51
+
52
+ from developers_chamber.scripts.version import *
53
+ from developers_chamber.scripts.project import *
54
+
55
+ click_completion.init()
56
+
57
+ # Import external scripts
58
+ for base_path in (Path.home(), Path.cwd()):
59
+ if (base_path / ".pydev" / "scripts" / "__init__.py").exists():
60
+ SourceFileLoader(
61
+ "*", str(base_path / ".pydev" / "scripts" / "__init__.py")
62
+ ).load_module()
63
+
64
+ from developers_chamber.scripts.init_aliasses import *
65
+
66
+ coloredlogs.install(milliseconds=True)
67
+
68
+
69
+ @cli.command()
70
+ @click.option(
71
+ "--append/--overwrite", help="Append the completion code to the file", default=None
72
+ )
73
+ @click.option(
74
+ "-i", "--case-insensitive/--no-case-insensitive", help="Case insensitive completion"
75
+ )
76
+ @click.argument(
77
+ "shell",
78
+ required=False,
79
+ type=click_completion.DocumentedChoice(click_completion.core.shells),
80
+ )
81
+ @click.argument("path", required=False)
82
+ def init_completion(append, case_insensitive, shell, path):
83
+ """Install the pydev completion"""
84
+ extra_env = {"_PYDEV_CASE_INSENSITIVE_COMPLETE": "ON"} if case_insensitive else {}
85
+ shell, path = click_completion.core.install(
86
+ shell=shell, path=path, append=append, extra_env=extra_env
87
+ )
88
+ click.echo("{} completion installed in {}".format(shell, path))
89
+
90
+
91
+ if __name__ == "__main__":
92
+ cli()
@@ -0,0 +1,94 @@
1
+ import requests
2
+ from click import UsageError
3
+ from requests.auth import HTTPBasicAuth
4
+
5
+
6
+ def get_commit_builds(username, password, repository_name, commit):
7
+ response = requests.get(
8
+ "https://api.bitbucket.org/2.0/repositories/{repository}/commit/{commit}/statuses".format(
9
+ repository=repository_name, commit=commit
10
+ ),
11
+ headers={"content-type": "application/json"},
12
+ auth=HTTPBasicAuth(username, password),
13
+ )
14
+ if response.status_code != 200:
15
+ raise UsageError("Bitbucket error: {}".format(response.content.decode("utf-8")))
16
+ return [
17
+ build_data
18
+ for build_data in response.json()["values"]
19
+ if build_data["type"] == "build"
20
+ ]
21
+
22
+
23
+ def get_current_user_uuid(username, password):
24
+ response = requests.get(
25
+ "https://api.bitbucket.org/2.0/user",
26
+ headers={"content-type": "application/json"},
27
+ auth=HTTPBasicAuth(username, password),
28
+ )
29
+ if response.status_code != 200:
30
+ raise UsageError("Bitbucket error: {}".format(response.content.decode("utf-8")))
31
+ return response.json()["uuid"]
32
+
33
+
34
+ def get_default_reviewers(username, password, repository_name):
35
+ url = "https://api.bitbucket.org/2.0/repositories/{repository}/default-reviewers".format(
36
+ repository=repository_name
37
+ )
38
+ response = requests.get(
39
+ url,
40
+ headers={"content-type": "application/json"},
41
+ auth=HTTPBasicAuth(username, password),
42
+ )
43
+ if response.status_code != 200:
44
+ raise UsageError("Bitbucket error: {}".format(response.content.decode("utf-8")))
45
+ current_user_uuid = get_current_user_uuid(username, password)
46
+ return [
47
+ {"uuid": reviewer_data["uuid"]}
48
+ for reviewer_data in response.json()["values"]
49
+ if reviewer_data["uuid"] != current_user_uuid
50
+ ]
51
+
52
+
53
+ def create_pull_request(
54
+ username,
55
+ password,
56
+ title,
57
+ description,
58
+ source_branch_name,
59
+ destination_branch_name,
60
+ repository_name,
61
+ ):
62
+ url = "https://api.bitbucket.org/2.0/repositories/{repository}/pullrequests".format(
63
+ repository=repository_name
64
+ )
65
+ json_data = {
66
+ "title": title,
67
+ "description": description,
68
+ "source": {"branch": {"name": source_branch_name}},
69
+ "destination": {"branch": {"name": destination_branch_name}},
70
+ "reviewers": get_default_reviewers(username, password, repository_name),
71
+ }
72
+ response = requests.post(
73
+ url,
74
+ headers={"content-type": "application/json"},
75
+ json=json_data,
76
+ auth=HTTPBasicAuth(username, password),
77
+ )
78
+ if response.status_code != 201:
79
+ raise UsageError("Bitbucket error: {}".format(response.content.decode("utf-8")))
80
+ return response.json()["links"]["html"]["href"]
81
+
82
+
83
+ def create_merge_release_pull_request(
84
+ username, password, source_branch_name, destination_branch_name, repository_name
85
+ ):
86
+ return create_pull_request(
87
+ username=username,
88
+ password=password,
89
+ title='Merge branch "{}"'.format(source_branch_name),
90
+ description="",
91
+ source_branch_name=source_branch_name,
92
+ destination_branch_name=destination_branch_name,
93
+ repository_name=repository_name,
94
+ )
File without changes
@@ -0,0 +1,130 @@
1
+ import re
2
+ import shlex
3
+ from gettext import gettext as _
4
+
5
+ import click
6
+ from click.formatting import wrap_text
7
+
8
+
9
+ def find_and_replace_command_variable(arg, command, index):
10
+ match = re.match(r"^--(?P<arg_name>[^=\ ]+)[\ =](?P<arg_value>.+)", arg)
11
+ if match:
12
+ arg_name, arg_value = match.groups()
13
+ if f"${arg_name}" in command:
14
+ return True, command.replace(f"${arg_name}", arg_value)
15
+ elif f'${arg_name.replace("-", "_")}' in command:
16
+ return True, command.replace(f'${arg_name.replace("-", "_")}', arg_value)
17
+ if f"${index}" in command:
18
+ return True, command.replace(f"${index}", arg)
19
+ return False, command
20
+
21
+
22
+ def parse_alias(alias):
23
+ from developers_chamber.scripts import cli
24
+
25
+ command_parts = list(shlex.split(alias))
26
+ used_command_parts = []
27
+
28
+ click_command = cli
29
+ while command_parts:
30
+ command_part = command_parts[0]
31
+ current_click_command = click_command.get_command(None, command_part)
32
+ if current_click_command is None:
33
+ raise click.ClickException(
34
+ 'Command to the alias "{}" cannot be found'.format(alias)
35
+ )
36
+
37
+ used_command_parts.append(command_parts.pop(0))
38
+ click_command = current_click_command
39
+ if not isinstance(current_click_command, click.Group):
40
+ break
41
+ return used_command_parts, command_parts, click_command, alias
42
+
43
+
44
+ class AliasCommand(click.Command):
45
+
46
+ def __init__(self, commands, *args, **kwargs):
47
+ super().__init__(*args, **kwargs)
48
+ self._parse_alias(commands)
49
+
50
+ def _parse_alias(self, commands):
51
+ if isinstance(commands, str):
52
+ commands = [commands]
53
+ description = ""
54
+ elif isinstance(commands, list):
55
+ commands = commands
56
+ description = ""
57
+ elif isinstance(commands, dict):
58
+ description = commands["description"]
59
+ commands = commands["command"]
60
+ else:
61
+ raise click.ClickException("Invalid alias type")
62
+
63
+ commands = [commands] if isinstance(commands, str) else commands
64
+ self.aliases = [(parse_alias(alias)) for alias in commands]
65
+ self.short_help = description
66
+
67
+ def format_help_text(self, ctx, formatter) -> None:
68
+ formatter.write_paragraph()
69
+ with formatter.indentation():
70
+ if self.short_help:
71
+ formatter.write_text(self.short_help)
72
+ formatter.write_paragraph()
73
+ formatter.write_text("Alias to commands: ")
74
+ with formatter.indentation():
75
+ for (
76
+ used_command_parts,
77
+ remaining_command_parts,
78
+ click_command,
79
+ alias_str,
80
+ ) in self.aliases:
81
+ formatter.write_text("* " + " ".join(used_command_parts))
82
+ if remaining_command_parts:
83
+ with formatter.indentation(), formatter.indentation():
84
+ formatter.write_text(" ".join(remaining_command_parts))
85
+
86
+ def format_epilog(self, ctx, formatter) -> None:
87
+ with formatter.section(_("Commands in alias help")):
88
+ for (
89
+ used_command_parts,
90
+ remaining_command_parts,
91
+ click_command,
92
+ alias_str,
93
+ ) in self.aliases:
94
+ with formatter.indentation():
95
+ formatter.write_paragraph()
96
+ formatter.write_text("* " + " ".join(used_command_parts))
97
+ with formatter.indentation(), formatter.indentation():
98
+ click_command.format_help_text(ctx, formatter)
99
+ click_command.format_options(ctx, formatter)
100
+ formatter.write_paragraph()
101
+
102
+ def shell_complete(self, ctx, param):
103
+ from click.shell_completion import CompletionItem
104
+
105
+ return [CompletionItem(param, type="file")]
106
+
107
+ def invoke(self, ctx):
108
+ from developers_chamber.scripts import cli
109
+
110
+ for i, (
111
+ used_command_parts,
112
+ remaining_command_parts,
113
+ click_command,
114
+ alias_str,
115
+ ) in enumerate(self.aliases):
116
+ if i == 0:
117
+ alias_args = []
118
+
119
+ for index, arg in enumerate(ctx.args, start=1):
120
+ replaced_arg, alias_str = find_and_replace_command_variable(
121
+ arg, alias_str, index
122
+ )
123
+ if not replaced_arg:
124
+ alias_args.append(arg)
125
+
126
+ if "$@" in alias_str:
127
+ alias_str = alias_str.replace("$@", " ".join(ctx.args))
128
+ alias_args = []
129
+
130
+ cli.main(args=shlex.split(alias_str) + alias_args, standalone_mode=False)
@@ -0,0 +1,86 @@
1
+ import click
2
+
3
+
4
+ class RequiredIfNotEmpty(click.Option):
5
+
6
+ def __init__(self, *args, **kwargs):
7
+ self.required_if_not_empty = kwargs.pop("required_if_empty")
8
+ if not self.required_if_not_empty:
9
+ raise ValueError(
10
+ '"required_if_not_empty" argument is required for "RequiredIfNotEmpty" option'
11
+ )
12
+ kwargs["help"] += " NOTE: This option is required with {}".format(
13
+ self.required_if_not_empty
14
+ )
15
+
16
+ super().__init__(*args, **kwargs)
17
+
18
+ def handle_parse_result(self, ctx, opts, args):
19
+ if self.required_if_not_empty in opts:
20
+ if self.name not in opts:
21
+ raise click.UsageError(
22
+ "Illegal usage: {} is required with {}".format(
23
+ self.name, self.required_if_not_empty
24
+ )
25
+ )
26
+ else:
27
+ self.prompt = None
28
+
29
+ return super().handle_parse_result(ctx, opts, args)
30
+
31
+
32
+ class ContainerDirToCopyType(click.ParamType):
33
+
34
+ name = "container_dir_to_copy"
35
+
36
+ def convert(self, value, param, ctx):
37
+ try:
38
+ container_name, container_dir, host_dir = value.split(":")
39
+ return container_name, container_dir, host_dir
40
+ except ValueError:
41
+ self.fail(
42
+ 'Invalid value "{}" format must be "DOCKER_CONTAINER_NAME:CONTAINER_DIRECTORY:HOST_DIRECTORY"'.format(
43
+ value
44
+ ),
45
+ param,
46
+ ctx,
47
+ )
48
+
49
+
50
+ class ContainerCommandType(click.ParamType):
51
+
52
+ name = "container_command_type"
53
+
54
+ def convert(self, value, param, ctx):
55
+ if value:
56
+ try:
57
+ container_name, command = value.split(":")
58
+ return container_name, command
59
+ except ValueError:
60
+ self.fail(
61
+ 'Invalid value "{}" format must be "DOCKER_CONTAINER_NAME:COMMAND"'.format(
62
+ value
63
+ ),
64
+ param,
65
+ ctx,
66
+ )
67
+
68
+
69
+ class ContainerEnvironment(click.ParamType):
70
+
71
+ name = "container_environment"
72
+
73
+ def convert(self, value, param, ctx):
74
+ try:
75
+ return {
76
+ variable.split("=")[0]: variable.split("=")[1]
77
+ for variable in value.split(" ")
78
+ }
79
+ except ValueError:
80
+ self.fail(
81
+ 'Invalid value "{}" format must be "NAME=VALUE [NAME2=VALUE2]"'.format(
82
+ value
83
+ ),
84
+ param,
85
+ ctx,
86
+ )
@@ -0,0 +1,15 @@
1
+ from developers_chamber.utils import call_command
2
+
3
+
4
+ def login_client(username, password, registry):
5
+ call_command(
6
+ ["docker", "login", "--username", username, "--password", password, registry]
7
+ )
8
+
9
+
10
+ def tag(source_image, target_image):
11
+ call_command(["docker", "tag", source_image, target_image])
12
+
13
+
14
+ def push_image(repository, tag):
15
+ call_command(["docker", "push", "{}:{}".format(repository, tag)])