diff --git a/config/django/django_settings.py b/config/django/django_settings.py index 0ac47c9..c6a4279 100644 --- a/config/django/django_settings.py +++ b/config/django/django_settings.py @@ -1,19 +1,19 @@ import os -import django_mongodb_backend -kms_providers = django_mongodb_backend.get_kms_providers() +from django_mongodb_backend import encryption, parse_uri + +kms_providers = encryption.get_kms_providers() HOME = os.environ.get("HOME") -auto_encryption_opts = django_mongodb_backend.get_auto_encryption_opts( +auto_encryption_opts = encryption.get_auto_encryption_opts( kms_providers=kms_providers, crypt_shared_lib_path=f"{HOME}/Downloads/mongo_crypt_shared_v1-macos-arm64-enterprise-8.0.10/lib/mongo_crypt_v1.dylib", ) DATABASE_URL = os.environ.get("MONGODB_URI", "mongodb://localhost:27017/djangotests") DATABASES = { - "default": django_mongodb_backend.parse_uri(DATABASE_URL), - "encryption": django_mongodb_backend.parse_uri( + "default": parse_uri( DATABASE_URL, options={"auto_encryption_opts": auto_encryption_opts} ), } diff --git a/django_mongodb_cli/repo.py b/django_mongodb_cli/repo.py index 8e9138a..aa58804 100644 --- a/django_mongodb_cli/repo.py +++ b/django_mongodb_cli/repo.py @@ -12,7 +12,6 @@ repo_clone, repo_install, repo_status, - repo_update, ) @@ -68,7 +67,7 @@ def repo(ctx, list_repos): @click.pass_context @pass_repo def clone(repo, ctx, repo_names, all_repos, install): - """Clone repositories from `pyproject.toml`.""" + """Clone and install repositories from `pyproject.toml`.""" repos, url_pattern, branch_pattern = get_repos("pyproject.toml") if repo_names: @@ -100,75 +99,39 @@ def clone(repo, ctx, repo_names, all_repos, install): click.echo(ctx.get_help()) -@repo.command() -@click.option( - "-a", - "--all-repos", - is_flag=True, -) -@click.argument("repo_names", nargs=-1) -@click.pass_context -@pass_repo -def install(repo, ctx, repo_names, all_repos): - """Install cloned repositories with `pip install -e`.""" - - if repo_names: - for repo_name in repo_names: - clone_path = os.path.join(ctx.obj.home, repo_name) - if os.path.exists(clone_path): - repo_install(clone_path) - else: - click.echo(f"Repository '{repo_name}' not found.") - return - - if all_repos: - repos, url_pattern, branch_pattern = get_repos("pyproject.toml") - for repo_entry in repos: - url_match = url_pattern.search(repo_entry) - if url_match: - repo_url = url_match.group(0) - repo_name = os.path.basename(repo_url) - clone_path = os.path.join(ctx.obj.home, repo_name) - if os.path.exists(clone_path): - repo_install(clone_path) - return - - if ctx.args == []: - click.echo(ctx.get_help()) - - -@repo.command() -@click.argument("repo_names", nargs=-1) -@click.option( - "-a", - "--all-repos", - is_flag=True, -) -@click.pass_context -@pass_repo -def update(repo, ctx, repo_names, all_repos): - """Update cloned repositories with `git pull`.""" - repos, url_pattern, _ = get_repos("pyproject.toml") - if repo_names: - for repo_name in repo_names: - for repo_entry in repos: - if ( - os.path.basename(url_pattern.search(repo_entry).group(0)) - == repo_name - ): - repo_update(repo_entry, url_pattern, repo) - return - click.echo(f"Repository '{repo_name}' not found.") - return - - if all_repos: - click.echo(f"Updating {len(repos)} repositories...") - for repo_entry in repos: - repo_update(repo_entry, url_pattern, repo) - return - - if ctx.args == []: - click.echo(ctx.get_help()) +# @repo.command() +# @click.argument("repo_names", nargs=-1) +# @click.option( +# "-a", +# "--all-repos", +# is_flag=True, +# ) +# @click.pass_context +# @pass_repo +# def update(repo, ctx, repo_names, all_repos): +# """Update cloned repositories with `git pull`.""" +# repos, url_pattern, _ = get_repos("pyproject.toml") +# if repo_names: +# for repo_name in repo_names: +# for repo_entry in repos: +# if ( +# os.path.basename(url_pattern.search(repo_entry).group(0)) +# == repo_name +# ): +# repo_update(repo_entry, url_pattern, repo) +# return +# click.echo(f"Repository '{repo_name}' not found.") +# return +# +# if all_repos: +# click.echo(f"Updating {len(repos)} repositories...") +# for repo_entry in repos: +# repo_update(repo_entry, url_pattern, repo) +# return +# +# if ctx.args == []: +# click.echo(ctx.get_help()) +# @repo.command(context_settings={"ignore_unknown_options": True}) @@ -240,8 +203,7 @@ def makemigrations( @click.argument("modules", nargs=-1) @click.option("-k", "--keyword", help="Filter tests by keyword") @click.option("-l", "--list-tests", help="List tests", is_flag=True) -@click.option("-s", "--setup", help="Setup tests (pymongo only)", is_flag=True) -@click.option("--show", help="Show settings", is_flag=True) +@click.option("-s", "--show", help="Show settings", is_flag=True) @click.pass_context def test( ctx, @@ -249,7 +211,6 @@ def test( modules, keyword, list_tests, - setup, show, ): """ @@ -259,6 +220,7 @@ def test( if repo_name: # Show test settings if show: + click.echo(f"⚙️ Test settings for 📦 {repo_name}:") if repo_name in test_settings_map.keys(): from rich import print from black import format_str as format @@ -286,7 +248,7 @@ def test( test_dirs = test_settings_map[repo_name]["test_dirs"] if list_tests: for test_dir in test_dirs: - click.echo(click.style(f"{test_dir}", fg="blue")) + click.echo(f"📂 {test_dir}") try: modules = sorted(os.listdir(test_dir)) count = 0 @@ -297,9 +259,17 @@ def test( and module != "__init__.py" ): if count == len(modules): - click.echo(f" └── {module}") + click.echo( + click.style( + f" └── {module}", fg="green" + ) + ) else: - click.echo(f" ├── {module}") + click.echo( + click.style( + f" └── {module}", fg="green" + ) + ) click.echo() except FileNotFoundError: click.echo( @@ -347,6 +317,7 @@ def test( "3", "--debug-sql", "--noinput", + "--keepdb", ] ) if keyword: @@ -407,9 +378,19 @@ def test( "--diff", is_flag=True, ) +@click.option( + "-b", + "--branch", + is_flag=True, +) +@click.option( + "-u", + "--update", + is_flag=True, +) @click.pass_context @pass_repo -def status(repo, ctx, repo_names, all_repos, reset, diff): +def status(repo, ctx, repo_names, all_repos, reset, diff, branch, update): """Repository status.""" repos, url_pattern, _ = get_repos("pyproject.toml") if repo_names: @@ -420,17 +401,34 @@ def status(repo, ctx, repo_names, all_repos, reset, diff): os.path.basename(url_pattern.search(repo_entry).group(0)) == repo_name ): - repo_status(repo_entry, url_pattern, repo, reset=reset, diff=diff) + repo_status( + repo_entry, + url_pattern, + repo, + reset=reset, + diff=diff, + branch=branch, + update=update, + ) return else: not_found.add(repo_name) - click.echo(f"Repository '{not_found.pop()}' not found.") + if not_found: + click.echo(f"Repository '{not_found.pop()}' not found.") return if all_repos: click.echo(f"Status of {len(repos)} repositories...") for repo_entry in repos: - repo_status(repo_entry, url_pattern, repo, reset=reset, diff=diff) + repo_status( + repo_entry, + url_pattern, + repo, + reset=reset, + diff=diff, + branch=branch, + update=update, + ) return if ctx.args == []: diff --git a/django_mongodb_cli/utils.py b/django_mongodb_cli/utils.py index 1a1908e..92c84af 100644 --- a/django_mongodb_cli/utils.py +++ b/django_mongodb_cli/utils.py @@ -106,7 +106,7 @@ def repo_clone(repo_entry, url_pattern, branch_pattern, repo): clone_path = os.path.join(repo.home, repo_name) if os.path.exists(clone_path): - click.echo(f"Skipping: {repo_name} already exists.") + click.echo(f"Skipping {repo_name}: already exists at {clone_path}") else: click.echo( f"Cloning {repo_name} from {repo_url} into {clone_path} (branch: {branch})" @@ -122,7 +122,7 @@ def repo_clone(repo_entry, url_pattern, branch_pattern, repo): click.echo(f"Failed to clone repository: {e}") subprocess.run(["pre-commit", "install"], cwd=clone_path) else: - click.echo(f"Skipping {repo_url} in {clone_path} (branch: {branch})") + click.echo(f"Skipping {repo_url}: already exists at {clone_path}") def repo_install(clone_path): @@ -149,7 +149,7 @@ def repo_install(clone_path): ) -def repo_update(repo_entry, url_pattern, repo): +def repo_update(repo_entry, url_pattern, clone_path): """Helper function to update a single repository.""" url_match = url_pattern.search(repo_entry) if not url_match: @@ -157,22 +157,23 @@ def repo_update(repo_entry, url_pattern, repo): repo_url = url_match.group(0) repo_name = os.path.basename(repo_url) - clone_path = os.path.join(repo.home, repo_name) if os.path.exists(clone_path): - click.echo(f"Updating {repo_name}...") try: + click.echo(f"Updating 📦 {repo_name}") repo = git.Repo(clone_path) - click.echo(click.style(repo.git.pull(), fg="blue")) + click.echo(repo.git.pull()) except git.exc.NoSuchPathError: - click.echo("Not a valid Git repository.") + click.echo(click.style("Not a valid Git repository.", fg="red")) except git.exc.GitCommandError: click.echo(click.style(f"Failed to update {repo_name}", fg="red")) else: - click.echo(f"Skipping {repo_name}: Repository not found at {clone_path}") + click.echo(click.style(f"Skipping {repo_name}", fg="blue")) -def repo_status(repo_entry, url_pattern, repo, reset=False, diff=False): +def repo_status( + repo_entry, url_pattern, repo, reset=False, diff=False, branch=False, update=False +): """Helper function to update a single repository.""" url_match = url_pattern.search(repo_entry) if not url_match: @@ -185,14 +186,17 @@ def repo_status(repo_entry, url_pattern, repo, reset=False, diff=False): if os.path.exists(clone_path): try: repo = git.Repo(clone_path) - click.echo(f"=== {repo_name} ===") + click.echo(f"📦 {repo_name}") if reset: - click.echo(click.style(repo.git.reset("--hard"), fg="blue")) + click.echo(click.style(f"Resetting {repo_name}", fg="red")) + click.echo(repo.git.reset("--hard")) else: - click.echo("Remote URLs:") click.echo( "".join( - [f"- {remote.name}:{remote.url}" for remote in repo.remotes] + [ + f"On remote {remote.name} at {remote.url}" + for remote in repo.remotes + ] ), ) click.echo(repo.git.status()) @@ -202,12 +206,17 @@ def repo_status(repo_entry, url_pattern, repo, reset=False, diff=False): click.echo(click.style(diff_output, fg="red")) else: click.echo(click.style("No diff output", fg="yellow")) + if branch: + click.echo(repo.git.branch("--all")) + if update: + repo_update(repo_entry, url_pattern, clone_path) + click.echo() except git.exc.NoSuchPathError: click.echo("Not a valid Git repository.") else: click.echo( click.style( - f"Skipping {repo_name}: Repository not found at {clone_path}", - fg="yellow", + f"Skipping 📦 {repo_name}", + fg="blue", ) ) diff --git a/justfile b/justfile index 53a6fd3..8c935a2 100644 --- a/justfile +++ b/justfile @@ -1,26 +1,20 @@ default: echo 'Hello, world!' -install: pip-install git-clone repo-install +install: pip-install git-clone alias i := install -repo-install: - dm repo install django - dm repo install django-mongodb-backend - dm repo install mongo-python-driver - # ---------------------------------------- git ---------------------------------------- [group('git')] git-clone: - dm repo clone django - dm repo clone django-allauth + dm repo clone django --install dm repo clone django-mongodb-app - dm repo clone django-mongodb-backend + dm repo clone django-mongodb-backend --install dm repo clone django-mongodb-extensions dm repo clone django-mongodb-project dm repo clone django-mongodb-templates - dm repo clone mongo-python-driver + dm repo clone mongo-python-driver --install # ---------------------------------------- django ---------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index 1eed2f8..34ee293 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,7 +35,6 @@ packages = ["django_mongodb_cli"] [tool.django_mongodb_cli] dev = [ - "DublinCityCenterPubFinder @ git+ssh://git@github.com/anaiyaraisin/DublinCityCenterPubFinder", "django @ git+ssh://git@github.com/mongodb-forks/django@mongodb-5.2.x", "django-allauth @ git+ssh://git@github.com/pennersr/django-allauth@main", "django-debug-toolbar @ git+ssh://git@github.com/django-commons/django-debug-toolbar@main", @@ -54,7 +53,6 @@ dev = [ "mongo-orchestration @ git+ssh://git@github.com/mongodb-labs/mongo-orchestration@master", "mongo-python-driver @ git+ssh://git@github.com/mongodb/mongo-python-driver@master", "pymongo-auth-aws @ git+ssh://git@github.com/mongodb/pymongo-auth-aws@main", - "pymongo-transactions @ git+ssh://git@github.com/aclark4life/pymongo-transactions@main", "specifications @ git+ssh://git@github.com/mongodb/specifications@master", "wagtail @ git+ssh://git@github.com/mongodb-forks/wagtail@main", "wagtail-mongodb-project @ git+ssh://git@github.com/mongodb-labs/wagtail-mongodb-project@main", diff --git a/qe.py b/qe.py index 6933c15..0851113 100644 --- a/qe.py +++ b/qe.py @@ -5,7 +5,8 @@ from bson.codec_options import CodecOptions from pymongo import MongoClient from pymongo.encryption import ClientEncryption -from django_mongodb_backend.utils import ( +from pymongo.errors import EncryptedCollectionError +from django_mongodb_backend.encryption import ( get_auto_encryption_opts, get_customer_master_key, ) @@ -18,19 +19,19 @@ }, } -encrypted_client = MongoClient( +client = MongoClient( auto_encryption_opts=get_auto_encryption_opts( crypt_shared_lib_path=f"{HOME}/Downloads/mongo_crypt_shared_v1-macos-arm64-enterprise-8.0.10/lib/mongo_crypt_v1.dylib", kms_providers=kms_providers, ) ) -key_vault_namespace = encrypted_client.options.auto_encryption_opts._key_vault_namespace +key_vault_namespace = client.options.auto_encryption_opts._key_vault_namespace codec_options = CodecOptions(uuid_representation=STANDARD) client_encryption = ClientEncryption( - kms_providers, key_vault_namespace, encrypted_client, codec_options + kms_providers, key_vault_namespace, client, codec_options ) -encrypted_database = encrypted_client["test"] +database = client["test"] encrypted_fields = { "fields": [ { @@ -44,7 +45,11 @@ }, ] } -encrypted_collection = client_encryption.create_encrypted_collection( - encrypted_database, "encrypted_collection", encrypted_fields, "local" -) +try: + encrypted_collection = client_encryption.create_encrypted_collection( + database, "encrypted_collection", encrypted_fields, "local" + ) +except EncryptedCollectionError as e: + print(f"Encrypted collection already exists: {e}") + code.interact(local=locals())