diff options
| author | Egor Tensin <egor@tensin.name> | 2026-06-23 18:06:51 +0200 |
|---|---|---|
| committer | Egor Tensin <egor@tensin.name> | 2026-06-23 18:06:51 +0200 |
| commit | ebbab9207fc3ec5dcf2df9011d945a8de2617983 (patch) | |
| tree | 9c01a22bc786ba6d30cb3e02d76f8b22b86107b6 | |
| parent | shorter level names in logs (diff) | |
| download | cgitize-ebbab9207fc3ec5dcf2df9011d945a8de2617983.tar.gz cgitize-ebbab9207fc3ec5dcf2df9011d945a8de2617983.zip | |
use default settings for Black
| -rw-r--r-- | cgitize/bitbucket.py | 4 | ||||
| -rw-r--r-- | cgitize/cgit.py | 46 | ||||
| -rw-r--r-- | cgitize/config.py | 70 | ||||
| -rw-r--r-- | cgitize/git.py | 64 | ||||
| -rw-r--r-- | cgitize/github.py | 4 | ||||
| -rw-r--r-- | cgitize/gitlab.py | 2 | ||||
| -rw-r--r-- | cgitize/header.py | 12 | ||||
| -rw-r--r-- | cgitize/main.py | 22 | ||||
| -rw-r--r-- | cgitize/repo.py | 58 | ||||
| -rw-r--r-- | cgitize/utils.py | 30 | ||||
| -rw-r--r-- | cgitize/version.py | 4 | ||||
| -rwxr-xr-x | docker/get_output_dir.py | 4 | ||||
| -rw-r--r-- | pyproject.toml | 3 | ||||
| -rw-r--r-- | test/unit/test_bitbucket.py | 62 | ||||
| -rw-r--r-- | test/unit/test_github.py | 52 | ||||
| -rw-r--r-- | test/unit/test_gitlab.py | 50 |
16 files changed, 242 insertions, 245 deletions
diff --git a/cgitize/bitbucket.py b/cgitize/bitbucket.py index 975e255..c8714fd 100644 --- a/cgitize/bitbucket.py +++ b/cgitize/bitbucket.py @@ -17,10 +17,10 @@ class Bitbucket: def get_repo(self, repo): try: - parts = repo.id.split('/') + parts = repo.id.split("/") if len(parts) != 2: raise ValueError( - f'repository ID must be in the USER/NAME format: {repo.id}' + f"repository ID must be in the USER/NAME format: {repo.id}" ) user, name = parts return self._impl.repositories.get(user, name) diff --git a/cgitize/cgit.py b/cgitize/cgit.py index 7691c61..0b9e381 100644 --- a/cgitize/cgit.py +++ b/cgitize/cgit.py @@ -27,20 +27,20 @@ class CGitRCWriter: @staticmethod def get_path(repo_dir): - return os.path.join(repo_dir, 'cgitrc') + return os.path.join(repo_dir, "cgitrc") def write(self, repo_dir, repo): - with open(self.get_path(repo_dir), 'w') as fd: - self._write_field(fd, 'clone-url', self._build_clone_url(repo)) - self._write_field(fd, 'owner', repo.owner) - self._write_field(fd, 'desc', repo.desc) - self._write_field(fd, 'homepage', repo.homepage) + with open(self.get_path(repo_dir), "w") as fd: + self._write_field(fd, "clone-url", self._build_clone_url(repo)) + self._write_field(fd, "owner", repo.owner) + self._write_field(fd, "desc", repo.desc) + self._write_field(fd, "homepage", repo.homepage) @staticmethod def _write_field(fd, field, value): if value is None: return - fd.write(f'{field}={value}\n') + fd.write(f"{field}={value}\n") def _build_clone_url(self, repo): clone_urls = [] @@ -51,7 +51,7 @@ class CGitRCWriter: clone_urls.append(repo.clone_url) if not clone_urls: return None - clone_urls = ' '.join(clone_urls) + clone_urls = " ".join(clone_urls) return clone_urls @@ -61,8 +61,8 @@ class AgeFile: timestamp = AgeFile.get_age(repo_dir) if timestamp: os.makedirs(AgeFile.get_dir(repo_dir), exist_ok=True) - with open(AgeFile.get_path(repo_dir), mode='w') as fd: - fd.write(f'{timestamp}') + with open(AgeFile.get_path(repo_dir), mode="w") as fd: + fd.write(f"{timestamp}") @staticmethod def get_age(repo_dir): @@ -71,10 +71,10 @@ class AgeFile: # represents activity. with chdir(repo_dir): success, output = Git.capture( - 'for-each-ref', - '--sort=-committerdate', - '--count=1', - '--format=%(committerdate:iso8601)', + "for-each-ref", + "--sort=-committerdate", + "--count=1", + "--format=%(committerdate:iso8601)", ) if not success: logging.error( @@ -86,11 +86,11 @@ class AgeFile: @staticmethod def get_dir(repo_dir): - return os.path.join(repo_dir, 'info', 'web') + return os.path.join(repo_dir, "info", "web") @staticmethod def get_path(repo_dir): - return os.path.join(AgeFile.get_dir(repo_dir), 'last-modified') + return os.path.join(AgeFile.get_dir(repo_dir), "last-modified") class CGitRepositories: @@ -123,16 +123,16 @@ class CGitRepositories: return self._mirror(repo) with chdir(repo_dir): - success, output = Git.capture('rev-parse', '--is-inside-work-tree') + success, output = Git.capture("rev-parse", "--is-inside-work-tree") if not success: # Overwrite the existing directory if it's not a Git repository. logging.warning( - 'Local directory is not a repository, going to overwrite it: %s', + "Local directory is not a repository, going to overwrite it: %s", repo_dir, ) return self._mirror(repo) - success, output = Git.capture('config', '--get', 'remote.origin.url') + success, output = Git.capture("config", "--get", "remote.origin.url") if not success: # Every repository managed by this script should have the # 'origin' remote. If it doesn't, it's trash. Overwrite the @@ -143,7 +143,7 @@ class CGitRepositories: ) return self._mirror(repo) - if f'{repo.clone_url}\n' != output: + if f"{repo.clone_url}\n" != output: # Jeez, there's a proper local repository in the target # directory already with a different upstream; something's # wrong, fix it manually. @@ -172,16 +172,16 @@ class CGitRepositories: logging.exception(e) return False with Git.setup_auth(repo): - return Git.check('clone', '--mirror', '--quiet', repo.clone_url, repo_dir) + return Git.check("clone", "--mirror", "--quiet", repo.clone_url, repo_dir) def _fix_upstream_url(self, repo): repo_dir = self.get_repo_dir(repo) with chdir(repo_dir): - return Git.check('remote', 'set-url', 'origin', repo.clone_url) + return Git.check("remote", "set-url", "origin", repo.clone_url) def _update_existing(self, repo): logging.info("Updating repository '%s'", repo.name) repo_dir = self.get_repo_dir(repo) with chdir(repo_dir): with Git.setup_auth(repo): - return Git.check('remote', 'update', '--prune') + return Git.check("remote", "update", "--prune") diff --git a/cgitize/config.py b/cgitize/config.py index fa4715c..dc1b341 100644 --- a/cgitize/config.py +++ b/cgitize/config.py @@ -22,7 +22,7 @@ class Section: def _get_config_value(self, key, required=True, default=None): if required and default is None: if not key in self.impl: - raise RuntimeError(f'configuration value is missing: {key}') + raise RuntimeError(f"configuration value is missing: {key}") return self.impl.get(key, default) def _get_config_path(self, *args, **kwargs): @@ -38,36 +38,36 @@ class Section: class MainSection(Section): - DEFAULT_OUTPUT_DIR = '/mnt/cgitize' + DEFAULT_OUTPUT_DIR = "/mnt/cgitize" @property def output_dir(self): return self._get_config_path( - 'output_dir', default=MainSection.DEFAULT_OUTPUT_DIR + "output_dir", default=MainSection.DEFAULT_OUTPUT_DIR ) @property def error_header_path(self): - return os.path.join(self.output_dir, 'error.html') + return os.path.join(self.output_dir, "error.html") @property def clone_url(self): - return self._get_config_value('clone_url', required=False) + return self._get_config_value("clone_url", required=False) @property def clone_via_ssh(self): - return self._get_config_value('clone_via_ssh', default=True) + return self._get_config_value("clone_via_ssh", default=True) @property def default_owner(self): - return self._get_config_value('owner', required=False) + return self._get_config_value("owner", required=False) class ServiceSection(Section, ABC): def __init__(self, impl): super().__init__(impl) - self.repositories = RepositoriesSection(self.impl.get('repositories', {})) - self.users = UsersSection(self.impl.get('users', {})) + self.repositories = RepositoriesSection(self.impl.get("repositories", {})) + self.users = UsersSection(self.impl.get("users", {})) def _enum_explicit_repositories(self, cfg, api): for r in self.repositories.enum_repositories(): @@ -99,15 +99,15 @@ class ServiceSection(Section, ABC): class GitHubSection(ServiceSection): def __init__(self, impl): super().__init__(impl) - self.orgs = OrgsSection(self.impl.get('organizations', {})) + self.orgs = OrgsSection(self.impl.get("organizations", {})) @property def token(self): - return self._get_config_or_env('token', 'CGITIZE_GITHUB_TOKEN') + return self._get_config_or_env("token", "CGITIZE_GITHUB_TOKEN") @property def username(self): - return self._get_config_or_env('username', 'CGITIZE_GITHUB_USERNAME') + return self._get_config_or_env("username", "CGITIZE_GITHUB_USERNAME") @property def url_auth(self): @@ -131,7 +131,7 @@ class GitHubSection(ServiceSection): token = self.token if (username is None) != (token is None): raise RuntimeError( - 'please set either both the GitHub username & token, or neither' + "please set either both the GitHub username & token, or neither" ) return GitHub(username, token) @@ -139,11 +139,11 @@ class GitHubSection(ServiceSection): class BitbucketSection(ServiceSection): @property def token(self): - return self._get_config_or_env('token', 'CGITIZE_BITBUCKET_TOKEN') + return self._get_config_or_env("token", "CGITIZE_BITBUCKET_TOKEN") @property def username(self): - return self._get_config_or_env('email', 'CGITIZE_BITBUCKET_EMAIL') + return self._get_config_or_env("email", "CGITIZE_BITBUCKET_EMAIL") @property def url_auth(self): @@ -154,7 +154,7 @@ class BitbucketSection(ServiceSection): token = self.token if (username is None) != (token is None): raise RuntimeError( - 'please set either both the Bitbucket username & token, or neither' + "please set either both the Bitbucket username & token, or neither" ) return Bitbucket(username, token) @@ -162,11 +162,11 @@ class BitbucketSection(ServiceSection): class GitLabSection(ServiceSection): @property def token(self): - return self._get_config_or_env('token', 'CGITIZE_GITLAB_TOKEN') + return self._get_config_or_env("token", "CGITIZE_GITLAB_TOKEN") @property def username(self): - return self._get_config_or_env('username', 'CGITIZE_GITLAB_USERNAME') + return self._get_config_or_env("username", "CGITIZE_GITLAB_USERNAME") @property def url_auth(self): @@ -177,7 +177,7 @@ class GitLabSection(ServiceSection): token = self.token if (username is None) != (token is None): raise RuntimeError( - 'please set either both the GitLab username & token, or neither' + "please set either both the GitLab username & token, or neither" ) return GitLab(token) @@ -200,56 +200,56 @@ class RepositoriesSection(Section): class Entity(ABC): @property def name(self): - return self._impl['name'] + return self._impl["name"] @property def dir(self): - return self._impl.get('dir') + return self._impl.get("dir") @property def skip(self): - return self._impl.get('skip', []) + return self._impl.get("skip", []) class User(Entity): def __init__(self, impl): - if 'name' not in impl: + if "name" not in impl: raise ValueError("every user must have a 'name'") self._impl = impl @property def public_repos(self): - return self._impl.get('public', True) + return self._impl.get("public", True) @property def private_repos(self): - return self._impl.get('private', False) + return self._impl.get("private", False) class Org(Entity): def __init__(self, impl): - if 'name' not in impl: + if "name" not in impl: raise ValueError("every organization must have a 'name'") self._impl = impl class HostedRepo: def __init__(self, impl): - if 'id' not in impl: + if "id" not in impl: raise ValueError("every hosted repository must have 'id'") self._impl = impl @property def id(self): - return self._impl['id'] + return self._impl["id"] @property def dir(self): - return self._impl.get('dir') + return self._impl.get("dir") class Config: - DEFAULT_PATH = '/etc/cgitize/cgitize.toml' + DEFAULT_PATH = "/etc/cgitize/cgitize.toml" @staticmethod def read(path): @@ -257,13 +257,13 @@ class Config: def __init__(self, path): self.path = os.path.abspath(path) - with open(self.path, 'rb') as f: + with open(self.path, "rb") as f: self.impl = tomli.load(f) self.main = MainSection(self.impl) - self.repositories = RepositoriesSection(self.impl.get('repositories', {})) - self.github = GitHubSection(self.impl.get('github', {})) - self.bitbucket = BitbucketSection(self.impl.get('bitbucket', {})) - self.gitlab = GitLabSection(self.impl.get('gitlab', {})) + self.repositories = RepositoriesSection(self.impl.get("repositories", {})) + self.github = GitHubSection(self.impl.get("github", {})) + self.bitbucket = BitbucketSection(self.impl.get("bitbucket", {})) + self.gitlab = GitLabSection(self.impl.get("gitlab", {})) def _parse_explicit_repositories(self): for r in self.repositories.enum_repositories(): diff --git a/cgitize/git.py b/cgitize/git.py index aba1f2b..6fb8423 100644 --- a/cgitize/git.py +++ b/cgitize/git.py @@ -9,8 +9,8 @@ import os from cgitize import utils GIT_ENV = os.environ.copy() -GIT_ENV['GIT_SSH_COMMAND'] = ( - 'ssh -oBatchMode=yes -oLogLevel=QUIET -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null' +GIT_ENV["GIT_SSH_COMMAND"] = ( + "ssh -oBatchMode=yes -oLogLevel=QUIET -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null" ) @@ -21,15 +21,15 @@ class Config: def exists(self): return os.path.exists(self.path) - def open(self, mode='r'): - return open(self.path, mode=mode, encoding='utf-8') + def open(self, mode="r"): + return open(self.path, mode=mode, encoding="utf-8") def read(self): - with self.open(mode='r') as fd: + with self.open(mode="r") as fd: return fd.read() def write(self, contents): - with self.open(mode='w') as fd: + with self.open(mode="w") as fd: fd.write(contents) @contextmanager @@ -52,12 +52,12 @@ class Config: @staticmethod def validate_name(name): if not name: - raise RuntimeError('section names cannot be empty') + raise RuntimeError("section names cannot be empty") for c in name: - if c.isalnum() or c == '-' or c == '.': + if c.isalnum() or c == "-" or c == ".": continue raise RuntimeError( - f'section names must only contain alphanumeric characters, . or -: {name}' + f"section names must only contain alphanumeric characters, . or -: {name}" ) @staticmethod @@ -65,8 +65,8 @@ class Config: return name def format(self): - result = f'[{self.format_name(self.name)}]\n' - result += ''.join((var.format() for var in self.variables)) + result = f"[{self.format_name(self.name)}]\n" + result += "".join((var.format() for var in self.variables)) return result class Subsection: @@ -79,23 +79,23 @@ class Config: @staticmethod def validate_name(name): - if '\n' in name: - raise RuntimeError(f'subsection names cannot contain newlines: {name}') + if "\n" in name: + raise RuntimeError(f"subsection names cannot contain newlines: {name}") def format_name(self): name = self.name # Escape the backslashes: - name = name.replace('\\', r'\\') + name = name.replace("\\", r"\\") # Escape the quotes: - name = name.replace('"', r'\"') + name = name.replace('"', r"\"") # Put in quotes: return f'"{name}"' def format(self): result = ( - f'[{Config.Section.format_name(self.section)} {self.format_name()}]\n' + f"[{Config.Section.format_name(self.section)} {self.format_name()}]\n" ) - result += ''.join((var.format() for var in self.variables)) + result += "".join((var.format() for var in self.variables)) return result class Variable: @@ -108,16 +108,16 @@ class Config: @staticmethod def validate_name(name): if not name: - raise RuntimeError('variable names cannot be empty') + raise RuntimeError("variable names cannot be empty") for c in name: - if c.isalnum() or c == '-': + if c.isalnum() or c == "-": continue raise RuntimeError( - f'variable name can only contain alphanumeric characters or -: {name}' + f"variable name can only contain alphanumeric characters or -: {name}" ) if not name[0].isalnum(): raise RuntimeError( - f'variable name must start with an alphanumeric character: {name}' + f"variable name must start with an alphanumeric character: {name}" ) @staticmethod @@ -130,23 +130,23 @@ class Config: def format_value(self): value = self.value # Escape the backslashes: - value = value.replace('\\', r'\\') + value = value.replace("\\", r"\\") # Escape the supported escape sequences (\n, \t and \b): - value = value.replace('\n', r'\n') - value = value.replace('\t', r'\t') - value = value.replace('\b', r'\b') + value = value.replace("\n", r"\n") + value = value.replace("\t", r"\t") + value = value.replace("\b", r"\b") # Escape the quotes: - value = value.replace('"', r'\"') + value = value.replace('"', r"\"") # Put in quotes: value = f'"{value}"' return value def format(self): - return f' {self.format_name()} = {self.format_value()}\n' + return f" {self.format_name()} = {self.format_value()}\n" class Git: - EXE = 'git' + EXE = "git" @staticmethod def check(*args, **kwargs): @@ -158,7 +158,7 @@ class Git: @staticmethod def get_global_config(): - return Config(os.path.expanduser('~/.gitconfig')) + return Config(os.path.expanduser("~/.gitconfig")) @staticmethod @contextmanager @@ -169,10 +169,10 @@ class Git: config = Git.get_global_config() with utils.protected_file(config.path): with config.backup() as old_contents: - variables = [Config.Variable('insteadOf', repo.clone_url)] + variables = [Config.Variable("insteadOf", repo.clone_url)] subsection = Config.Subsection( - 'url', repo.clone_url_with_auth, variables + "url", repo.clone_url_with_auth, variables ) - new_contents = f'{old_contents}\n{subsection.format()}' + new_contents = f"{old_contents}\n{subsection.format()}" config.write(new_contents) yield diff --git a/cgitize/github.py b/cgitize/github.py index b03e085..735a733 100644 --- a/cgitize/github.py +++ b/cgitize/github.py @@ -34,13 +34,13 @@ class GitHub: # None makes no difference. kwargs = {} if visibility is not None: - kwargs['visibility'] = visibility + kwargs["visibility"] = visibility try: if user.name == self._username: # To get private repositories, get_user() must be called # without arguments: - return self._impl.get_user().get_repos(affiliation='owner', **kwargs) + return self._impl.get_user().get_repos(affiliation="owner", **kwargs) else: return self._impl.get_user(user.name).get_repos(**kwargs) except GithubException: diff --git a/cgitize/gitlab.py b/cgitize/gitlab.py index 01a4310..59bf7bd 100644 --- a/cgitize/gitlab.py +++ b/cgitize/gitlab.py @@ -13,7 +13,7 @@ from cgitize.repo import Repo, Visibility class GitLab: def __init__(self, token): - self._impl = Gitlab('https://gitlab.com', private_token=token) + self._impl = Gitlab("https://gitlab.com", private_token=token) def get_repo(self, repo): try: diff --git a/cgitize/header.py b/cgitize/header.py index e513411..8d7ef81 100644 --- a/cgitize/header.py +++ b/cgitize/header.py @@ -5,14 +5,14 @@ def update(path, success, error=None): - with open(path, 'w') as file: - contents = '' + with open(path, "w") as file: + contents = "" if not success: contents = ( - '''<p style="text-align: center; color: red; font-weight: bold;">''' + """<p style="text-align: center; color: red; font-weight: bold;">""" ) - contents += '''Some repositories couldn't be updated, please check application logs for details.''' + contents += """Some repositories couldn't be updated, please check application logs for details.""" if error is not None: - contents += f'''<br>{type(error).__name__}: {error}''' - contents += '''</p>\n''' + contents += f"""<br>{type(error).__name__}: {error}""" + contents += """</p>\n""" file.write(contents) diff --git a/cgitize/main.py b/cgitize/main.py index e99456e..688b46e 100644 --- a/cgitize/main.py +++ b/cgitize/main.py @@ -19,23 +19,23 @@ def parse_args(argv=None): argv = sys.argv[1:] parser = ArgumentParser() parser.add_argument( - '--config', - '-c', - metavar='PATH', + "--config", + "-c", + metavar="PATH", default=Config.DEFAULT_PATH, - help='config file path', + help="config file path", ) parser.add_argument( - '--repo', metavar='REPO_ID', nargs='*', dest='repos', help='repos to pull' + "--repo", metavar="REPO_ID", nargs="*", dest="repos", help="repos to pull" ) parser.add_argument( - '--force', '-f', action='store_true', help='overwrite existing repositories' + "--force", "-f", action="store_true", help="overwrite existing repositories" ) parser.add_argument( - '--verbose', '-v', action='store_true', help='verbose log output' + "--verbose", "-v", action="store_true", help="verbose log output" ) parser.add_argument( - '--version', '-V', action='version', version=f'%(prog)s {__version__}' + "--version", "-V", action="version", version=f"%(prog)s {__version__}" ) return parser.parse_args(argv) @@ -60,15 +60,15 @@ def main(argv=None): error = e if success: - logging.info('All repositories were updated successfully') + logging.info("All repositories were updated successfully") else: logging.warning("Some repositories couldn't be updated!") if error is not None: - logging.warning('Error: %s', error) + logging.warning("Error: %s", error) update_header(config.main.error_header_path, success, error) return int(not success) -if __name__ == '__main__': +if __name__ == "__main__": sys.exit(main()) diff --git a/cgitize/repo.py b/cgitize/repo.py index 5982247..8885adb 100644 --- a/cgitize/repo.py +++ b/cgitize/repo.py @@ -10,9 +10,9 @@ from cgitize.utils import url_remove_auth, url_replace_auth class Visibility(Enum): - ALL = 'all' - PUBLIC = 'public' - PRIVATE = 'private' + ALL = "all" + PUBLIC = "public" + PRIVATE = "private" def __str__(self): return self.name @@ -23,7 +23,7 @@ class Visibility(Enum): return Visibility.ALL if not public and not private: raise RuntimeError( - 'you need to fetch either public or private repos, or both' + "you need to fetch either public or private repos, or both" ) if public: return Visibility.PUBLIC @@ -35,45 +35,45 @@ class Visibility(Enum): if self is Visibility.ALL: return None if self is Visibility.PUBLIC: - return 'is_private=False' + return "is_private=False" if self is Visibility.PRIVATE: - return 'is_private=True' - raise NotImplementedError(f'not implemented visibility level: {self}') + return "is_private=True" + raise NotImplementedError(f"not implemented visibility level: {self}") def to_github_arg(self): # https://docs.github.com/en/rest/repos/repos?apiVersion=2026-03-10#list-repositories-for-the-authenticated-user if self is Visibility.ALL: return None if self is Visibility.PUBLIC: - return 'public' + return "public" if self is Visibility.PRIVATE: - return 'private' - raise NotImplementedError(f'not implemented visibility level: {self}') + return "private" + raise NotImplementedError(f"not implemented visibility level: {self}") def to_gitlab_arg(self): # https://python-gitlab.readthedocs.io/en/stable/gl_objects/projects.html#projects if self is Visibility.ALL: return None if self is Visibility.PUBLIC: - return 'public' + return "public" if self is Visibility.PRIVATE: - return 'private' - raise NotImplementedError(f'not implemented visibility level: {self}') + return "private" + raise NotImplementedError(f"not implemented visibility level: {self}") class Repo: @staticmethod def from_config(src, config): - if 'name' not in src: + if "name" not in src: raise ValueError("every repository must have 'name'") - name = src['name'] - desc = src.get('desc') - homepage = src.get('homepage') - owner = src.get('owner', config.main.default_owner) - if 'clone_url' not in src: + name = src["name"] + desc = src.get("desc") + homepage = src.get("homepage") + owner = src.get("owner", config.main.default_owner) + if "clone_url" not in src: raise ValueError("every repository must have 'clone_url'") - clone_url = src['clone_url'] - subdir = src.get('dir') + clone_url = src["clone_url"] + subdir = src.get("dir") return Repo( name, clone_url, owner=owner, desc=desc, homepage=homepage, subdir=subdir ) @@ -108,23 +108,23 @@ class Repo: def from_bitbucket(src, config, subdir=None): name = src.name desc = src.description - homepage = src.get_link('html') - owner = src.data['owner']['display_name'] + homepage = src.get_link("html") + owner = src.data["owner"]["display_name"] https_urls = [ - link for link in src.data['links']['clone'] if link['name'] == 'https' + link for link in src.data["links"]["clone"] if link["name"] == "https" ] if len(https_urls) != 1: raise RuntimeError(f"no https:// clone URL for repository '{name}'?!") # Bitbucket leaves the username in the URL... Sigh. - api_auth, https_url = url_remove_auth(https_urls[0]['href']) + api_auth, https_url = url_remove_auth(https_urls[0]["href"]) ssh_urls = [ - link for link in src.data['links']['clone'] if link['name'] == 'ssh' + link for link in src.data["links"]["clone"] if link["name"] == "ssh" ] if len(ssh_urls) != 1: raise RuntimeError(f"no ssh:// clone URL for repository '{name}'?!") - ssh_url = ssh_urls[0]['href'] + ssh_url = ssh_urls[0]["href"] clone_url = ssh_url url_auth = None @@ -154,7 +154,7 @@ class Repo: name = src.name desc = src.description homepage = src.web_url - owner = src.namespace['name'] + owner = src.namespace["name"] https_url = src.http_url_to_repo ssh_url = src.ssh_url_to_repo @@ -199,7 +199,7 @@ class Repo: @property def namegit(self): - return f'{self.name}.git' + return f"{self.name}.git" @property def desc(self): diff --git a/cgitize/utils.py b/cgitize/utils.py index 9ec8dd3..c924938 100644 --- a/cgitize/utils.py +++ b/cgitize/utils.py @@ -15,11 +15,11 @@ from urllib.parse import quote, urlsplit, urlunsplit @contextmanager def setup_logging(verbose=False): level_names = { - logging.DEBUG: 'DBG', - logging.INFO: 'INFO', - logging.WARNING: 'WARN', - logging.ERROR: 'ERR', - logging.CRITICAL: 'CRIT', + logging.DEBUG: "DBG", + logging.INFO: "INFO", + logging.WARNING: "WARN", + logging.ERROR: "ERR", + logging.CRITICAL: "CRIT", } for lvl, name in level_names.items(): logging.addLevelName(lvl, name) @@ -27,8 +27,8 @@ def setup_logging(verbose=False): level = logging.DEBUG if verbose else logging.INFO logging.basicConfig( level=level, - datefmt='%Y-%m-%d %H:%M:%S%z', - format='%(asctime)s | %(levelname)4s | %(message)s', + datefmt="%Y-%m-%d %H:%M:%S%z", + format="%(asctime)s | %(levelname)4s | %(message)s", # Log to stdout, because that's where subprocess's output goes (so that # they don't get interleaved). stream=sys.stdout, @@ -47,13 +47,13 @@ def run(*args, capture_output=False, **kwargs): stdout = subprocess.PIPE stderr = subprocess.STDOUT - logging.debug('%s', args) + logging.debug("%s", args) result = subprocess.run( - args, check=True, stdout=stdout, stderr=stderr, encoding='utf-8', **kwargs + args, check=True, stdout=stdout, stderr=stderr, encoding="utf-8", **kwargs ) if result.stdout is not None: - logging.debug('\n%s', result.stdout) + logging.debug("\n%s", result.stdout) return result.stdout @@ -98,7 +98,7 @@ def protected_file(path): finally: os.chmod(path, old_permissions) else: - with open(path, mode='w'): + with open(path, mode="w"): pass os.chmod(path, new_permissions) try: @@ -112,10 +112,10 @@ def url_replace_auth(url, auth): parts = urlsplit(url) netloc = quote(username) if password is not None: - netloc += f':{quote(password)}' - netloc += f'@{parts.hostname}' + netloc += f":{quote(password)}" + netloc += f"@{parts.hostname}" if parts.port is not None: - netloc += f':{parts.port}' + netloc += f":{parts.port}" parts = parts._replace(netloc=netloc) return urlunsplit(parts) @@ -125,6 +125,6 @@ def url_remove_auth(url): auth = parts.username, parts.password netloc = parts.hostname if parts.port is not None: - netloc += f':{parts.port}' + netloc += f":{parts.port}" parts = parts._replace(netloc=netloc) return auth, urlunsplit(parts) diff --git a/cgitize/version.py b/cgitize/version.py index 6d41cb8..e4edfd6 100644 --- a/cgitize/version.py +++ b/cgitize/version.py @@ -5,6 +5,6 @@ except ImportError: try: - __version__ = metadata.version('cgitize') + __version__ = metadata.version("cgitize") except Exception: - __version__ = 'unknown' + __version__ = "unknown" diff --git a/docker/get_output_dir.py b/docker/get_output_dir.py index ff0d35a..0b03e05 100755 --- a/docker/get_output_dir.py +++ b/docker/get_output_dir.py @@ -10,7 +10,7 @@ def parse_args(argv=None): if argv is None: argv = sys.argv[1:] parser = ArgumentParser() - parser.add_argument('config', metavar='PATH', help='config file path') + parser.add_argument("config", metavar="PATH", help="config file path") return parser.parse_args(argv) @@ -20,5 +20,5 @@ def main(argv=None): print(cfg.main.output_dir) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/pyproject.toml b/pyproject.toml index e8def91..e36635b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,6 +39,3 @@ cgitize = "cgitize.main:main" packages = ["cgitize"] [tool.setuptools_scm] - -[tool.black] -skip-string-normalization = true diff --git a/test/unit/test_bitbucket.py b/test/unit/test_bitbucket.py index e81cdef..29b69ff 100644 --- a/test/unit/test_bitbucket.py +++ b/test/unit/test_bitbucket.py @@ -13,80 +13,80 @@ from requests.exceptions import HTTPError class BitbucketTests(unittest.TestCase): def setUp(self): self.bitbucket = Cloud( - username=os.environ.get('CGITIZE_BITBUCKET_EMAIL'), - password=os.environ.get('CGITIZE_BITBUCKET_TOKEN'), + username=os.environ.get("CGITIZE_BITBUCKET_EMAIL"), + password=os.environ.get("CGITIZE_BITBUCKET_TOKEN"), cloud=True, ) def test_nonexistent_repo(self): with self.assertRaises(HTTPError): - self.bitbucket.repositories.get('doesnot', 'exist') + self.bitbucket.repositories.get("doesnot", "exist") def test_public_repo(self): - r = self.bitbucket.repositories.get('cgitize-test-workspace', 'public') - self.assertEqual(r.name, 'public') - self.assertEqual(r.description, 'Public test cgitize repository') + r = self.bitbucket.repositories.get("cgitize-test-workspace", "public") + self.assertEqual(r.name, "public") + self.assertEqual(r.description, "Public test cgitize repository") - self.assertEqual(r.data['workspace']['name'], 'Test cgitize workspace') - self.assertEqual(r.data['workspace']['slug'], 'cgitize-test-workspace') + self.assertEqual(r.data["workspace"]["name"], "Test cgitize workspace") + self.assertEqual(r.data["workspace"]["slug"], "cgitize-test-workspace") - self.assertFalse(r.data['is_private']) + self.assertFalse(r.data["is_private"]) self.assertEqual( - r.get_link('html'), 'https://bitbucket.org/cgitize-test-workspace/public' + r.get_link("html"), "https://bitbucket.org/cgitize-test-workspace/public" ) clone_urls = [ - link for link in r.data['links']['clone'] if link['name'] == 'https' + link for link in r.data["links"]["clone"] if link["name"] == "https" ] self.assertEqual(len(clone_urls), 1) self.assertEqual( - clone_urls[0]['href'], - 'https://cgitize-test@bitbucket.org/cgitize-test-workspace/public.git', + clone_urls[0]["href"], + "https://cgitize-test@bitbucket.org/cgitize-test-workspace/public.git", ) - ssh_urls = [link for link in r.data['links']['clone'] if link['name'] == 'ssh'] + ssh_urls = [link for link in r.data["links"]["clone"] if link["name"] == "ssh"] self.assertEqual(len(ssh_urls), 1) self.assertEqual( - ssh_urls[0]['href'], 'git@bitbucket.org:cgitize-test-workspace/public.git' + ssh_urls[0]["href"], "git@bitbucket.org:cgitize-test-workspace/public.git" ) def test_private_repo(self): - r = self.bitbucket.repositories.get('cgitize-test-workspace', 'private') - self.assertEqual(r.name, 'private') - self.assertEqual(r.description, 'Private test cgitize repository') + r = self.bitbucket.repositories.get("cgitize-test-workspace", "private") + self.assertEqual(r.name, "private") + self.assertEqual(r.description, "Private test cgitize repository") - self.assertEqual(r.data['workspace']['name'], 'Test cgitize workspace') - self.assertEqual(r.data['workspace']['slug'], 'cgitize-test-workspace') + self.assertEqual(r.data["workspace"]["name"], "Test cgitize workspace") + self.assertEqual(r.data["workspace"]["slug"], "cgitize-test-workspace") - self.assertTrue(r.data['is_private']) + self.assertTrue(r.data["is_private"]) self.assertEqual( - r.get_link('html'), 'https://bitbucket.org/cgitize-test-workspace/private' + r.get_link("html"), "https://bitbucket.org/cgitize-test-workspace/private" ) clone_urls = [ - link for link in r.data['links']['clone'] if link['name'] == 'https' + link for link in r.data["links"]["clone"] if link["name"] == "https" ] self.assertEqual(len(clone_urls), 1) self.assertEqual( - clone_urls[0]['href'], - 'https://cgitize-test@bitbucket.org/cgitize-test-workspace/private.git', + clone_urls[0]["href"], + "https://cgitize-test@bitbucket.org/cgitize-test-workspace/private.git", ) - ssh_urls = [link for link in r.data['links']['clone'] if link['name'] == 'ssh'] + ssh_urls = [link for link in r.data["links"]["clone"] if link["name"] == "ssh"] self.assertEqual(len(ssh_urls), 1) self.assertEqual( - ssh_urls[0]['href'], 'git@bitbucket.org:cgitize-test-workspace/private.git' + ssh_urls[0]["href"], "git@bitbucket.org:cgitize-test-workspace/private.git" ) def test_user(self): - w = self.bitbucket.workspaces.get('cgitize-test-workspace') + w = self.bitbucket.workspaces.get("cgitize-test-workspace") self.assertEqual( - len([r for r in w.repositories.each() if r.name == 'public']), 1 + len([r for r in w.repositories.each() if r.name == "public"]), 1 ) self.assertEqual( - len([r for r in w.repositories.each() if r.name == 'private']), 1 + len([r for r in w.repositories.each() if r.name == "private"]), 1 ) @@ -96,4 +96,4 @@ class BitbucketTestPrivateRepo(unittest.TestCase): def test_private_repo(self): with self.assertRaises(HTTPError): - self.bitbucket.repositories.get('cgitize-test-workspace', 'private') + self.bitbucket.repositories.get("cgitize-test-workspace", "private") diff --git a/test/unit/test_github.py b/test/unit/test_github.py index 054234b..45e7360 100644 --- a/test/unit/test_github.py +++ b/test/unit/test_github.py @@ -11,46 +11,46 @@ from github import Auth, Github, GithubException class GitHubTests(unittest.TestCase): def setUp(self): - self.github = Github(auth=Auth.Token(os.environ.get('CGITIZE_GITHUB_TOKEN'))) + self.github = Github(auth=Auth.Token(os.environ.get("CGITIZE_GITHUB_TOKEN"))) def test_nonexistent_repo(self): with self.assertRaises(GithubException): - self.github.get_repo('doesnot/exist') + self.github.get_repo("doesnot/exist") def test_public_repo(self): - r = self.github.get_repo('cgitize-test/public') - self.assertEqual(r.name, 'public') - self.assertEqual(r.description, 'Public test cgitize repository') - self.assertEqual(r.owner.name, 'Test cgitize user') - self.assertEqual(r.owner.login, 'cgitize-test') - self.assertEqual(r.visibility, 'public') - self.assertEqual(r.html_url, 'https://github.com/cgitize-test/public') - self.assertEqual(r.clone_url, 'https://github.com/cgitize-test/public.git') - self.assertEqual(r.ssh_url, 'git@github.com:cgitize-test/public.git') + r = self.github.get_repo("cgitize-test/public") + self.assertEqual(r.name, "public") + self.assertEqual(r.description, "Public test cgitize repository") + self.assertEqual(r.owner.name, "Test cgitize user") + self.assertEqual(r.owner.login, "cgitize-test") + self.assertEqual(r.visibility, "public") + self.assertEqual(r.html_url, "https://github.com/cgitize-test/public") + self.assertEqual(r.clone_url, "https://github.com/cgitize-test/public.git") + self.assertEqual(r.ssh_url, "git@github.com:cgitize-test/public.git") def test_private_repo(self): - r = self.github.get_repo('cgitize-test/private') - self.assertEqual(r.name, 'private') - self.assertEqual(r.description, 'Private test cgitize repository') - self.assertEqual(r.owner.name, 'Test cgitize user') - self.assertEqual(r.owner.login, 'cgitize-test') - self.assertEqual(r.visibility, 'private') - self.assertEqual(r.html_url, 'https://github.com/cgitize-test/private') - self.assertEqual(r.clone_url, 'https://github.com/cgitize-test/private.git') - self.assertEqual(r.ssh_url, 'git@github.com:cgitize-test/private.git') + r = self.github.get_repo("cgitize-test/private") + self.assertEqual(r.name, "private") + self.assertEqual(r.description, "Private test cgitize repository") + self.assertEqual(r.owner.name, "Test cgitize user") + self.assertEqual(r.owner.login, "cgitize-test") + self.assertEqual(r.visibility, "private") + self.assertEqual(r.html_url, "https://github.com/cgitize-test/private") + self.assertEqual(r.clone_url, "https://github.com/cgitize-test/private.git") + self.assertEqual(r.ssh_url, "git@github.com:cgitize-test/private.git") def test_user(self): # This is a bad way to get user's repositories: it'll return only # public ones for on particular reason. - rs = self.github.get_user('cgitize-test').get_repos() - self.assertEqual(len([r for r in rs if r.name == 'public']), 1) - self.assertEqual(len([r for r in rs if r.name == 'private']), 0) + rs = self.github.get_user("cgitize-test").get_repos() + self.assertEqual(len([r for r in rs if r.name == "public"]), 1) + self.assertEqual(len([r for r in rs if r.name == "private"]), 0) def test_user_authenticated(self): # This is the way instead: rs = self.github.get_user().get_repos() - self.assertEqual(len([r for r in rs if r.name == 'public']), 1) - self.assertEqual(len([r for r in rs if r.name == 'private']), 1) + self.assertEqual(len([r for r in rs if r.name == "public"]), 1) + self.assertEqual(len([r for r in rs if r.name == "private"]), 1) class GitHubTestPrivateRepo(unittest.TestCase): @@ -59,4 +59,4 @@ class GitHubTestPrivateRepo(unittest.TestCase): def test_private_repo(self): with self.assertRaises(GithubException): - self.github.get_repo('cgitize-test/private') + self.github.get_repo("cgitize-test/private") diff --git a/test/unit/test_gitlab.py b/test/unit/test_gitlab.py index f0b3b4a..cb34f47 100644 --- a/test/unit/test_gitlab.py +++ b/test/unit/test_gitlab.py @@ -13,53 +13,53 @@ from gitlab.exceptions import GitlabGetError class GitLabTests(unittest.TestCase): def setUp(self): self.gitlab = Gitlab( - 'https://gitlab.com', private_token=os.environ.get('CGITIZE_GITLAB_TOKEN') + "https://gitlab.com", private_token=os.environ.get("CGITIZE_GITLAB_TOKEN") ) def test_nonexistent_repo(self): with self.assertRaises(GitlabGetError): - self.gitlab.projects.get('doesnot/exist') + self.gitlab.projects.get("doesnot/exist") def test_public_repo(self): - r = self.gitlab.projects.get('cgitize-test/public') - self.assertEqual(r.name, 'public') - self.assertEqual(r.description, 'Public test cgitize repository') - self.assertEqual(r.namespace['name'], 'Test cgitize user') - self.assertEqual(r.namespace['path'], 'cgitize-test') - self.assertEqual(r.visibility, 'public') - self.assertEqual(r.web_url, 'https://gitlab.com/cgitize-test/public') + r = self.gitlab.projects.get("cgitize-test/public") + self.assertEqual(r.name, "public") + self.assertEqual(r.description, "Public test cgitize repository") + self.assertEqual(r.namespace["name"], "Test cgitize user") + self.assertEqual(r.namespace["path"], "cgitize-test") + self.assertEqual(r.visibility, "public") + self.assertEqual(r.web_url, "https://gitlab.com/cgitize-test/public") self.assertEqual( - r.http_url_to_repo, 'https://gitlab.com/cgitize-test/public.git' + r.http_url_to_repo, "https://gitlab.com/cgitize-test/public.git" ) - self.assertEqual(r.ssh_url_to_repo, 'git@gitlab.com:cgitize-test/public.git') + self.assertEqual(r.ssh_url_to_repo, "git@gitlab.com:cgitize-test/public.git") def test_private_repo(self): - r = self.gitlab.projects.get('cgitize-test/private') - self.assertEqual(r.name, 'private') - self.assertEqual(r.description, 'Private test cgitize repository') - self.assertEqual(r.namespace['name'], 'Test cgitize user') - self.assertEqual(r.namespace['path'], 'cgitize-test') - self.assertEqual(r.visibility, 'private') - self.assertEqual(r.web_url, 'https://gitlab.com/cgitize-test/private') + r = self.gitlab.projects.get("cgitize-test/private") + self.assertEqual(r.name, "private") + self.assertEqual(r.description, "Private test cgitize repository") + self.assertEqual(r.namespace["name"], "Test cgitize user") + self.assertEqual(r.namespace["path"], "cgitize-test") + self.assertEqual(r.visibility, "private") + self.assertEqual(r.web_url, "https://gitlab.com/cgitize-test/private") self.assertEqual( - r.http_url_to_repo, 'https://gitlab.com/cgitize-test/private.git' + r.http_url_to_repo, "https://gitlab.com/cgitize-test/private.git" ) - self.assertEqual(r.ssh_url_to_repo, 'git@gitlab.com:cgitize-test/private.git') + self.assertEqual(r.ssh_url_to_repo, "git@gitlab.com:cgitize-test/private.git") def test_user(self): - u = self.gitlab.users.list(username='cgitize-test') + u = self.gitlab.users.list(username="cgitize-test") self.assertEqual(len(u), 1) u = u[0] rs = u.projects.list() - self.assertEqual(len([r for r in rs if r.name == 'public']), 1) - self.assertEqual(len([r for r in rs if r.name == 'private']), 1) + self.assertEqual(len([r for r in rs if r.name == "public"]), 1) + self.assertEqual(len([r for r in rs if r.name == "private"]), 1) class GitLabTestPrivateRepo(unittest.TestCase): def setUp(self): - self.gitlab = Gitlab('https://gitlab.com') + self.gitlab = Gitlab("https://gitlab.com") def test_private_repo(self): with self.assertRaises(GitlabGetError): - self.gitlab.projects.get('cgitize-test/private') + self.gitlab.projects.get("cgitize-test/private") |
