From cd7fd2852d2da4dd4fb47ab6fcce1a59718173e3 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Fri, 24 May 2024 16:37:00 -0700 Subject: [PATCH 01/36] update CHANGELOG.md for 5.0.0 --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9dbfd104..e2cebabe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ All notable changes to this project will be documented in this file. ### Added -- Version checking for the `op` CLI tool at run-time +- Version checking for the `op` CLI tool at run-time (gh-162) - `opversion` command - Export `OPCLIVersion` as API - `OPCLIVersionSupportException` class @@ -21,7 +21,7 @@ All notable changes to this project will be documented in this file. ### Misc -- Remove `op` version checks for special behaviors where the version is no longer supported +- Remove `op` version checks for special behaviors where the version is no longer supported (gh-193) ## [4.3.0] 2024-03-28 From c3e7bd834e940040ac2af8068471f7644143201f Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Sat, 25 May 2024 10:45:17 -0700 Subject: [PATCH 02/36] bump version to 5.0.1.dev0 --- pyonepassword/__about__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyonepassword/__about__.py b/pyonepassword/__about__.py index 54b5a137..7f187b48 100644 --- a/pyonepassword/__about__.py +++ b/pyonepassword/__about__.py @@ -1,5 +1,5 @@ __title__ = "pyonepassword" -__version__ = "5.0.0" +__version__ = "5.0.1.dev0" __summary__ = "A python API to query a 1Password account using the 'op' command-line tool" """ From 6b62a73701e7801ae38a10637a6a5e0506c0ba78 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Sat, 25 May 2024 10:45:36 -0700 Subject: [PATCH 03/36] fix case of "testing and linting" workflow --- .github/workflows/testing-linting.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/testing-linting.yml b/.github/workflows/testing-linting.yml index 5a8d6983..65e3fc05 100644 --- a/.github/workflows/testing-linting.yml +++ b/.github/workflows/testing-linting.yml @@ -1,7 +1,7 @@ # This workflow will install Python dependencies, run tests and lint with a variety of Python versions # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions -name: testing and linting +name: Testing and Linting on: push: From 8e396ca047ec0fbd7b454d93bbbff7e76be46c34 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 20:08:34 +0000 Subject: [PATCH 04/36] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/hhatto/autopep8: v2.1.0 → v2.1.1](https://github.com/hhatto/autopep8/compare/v2.1.0...v2.1.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4ccb8a14..e5258d2d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/hhatto/autopep8 - rev: 'v2.1.0' + rev: 'v2.1.1' hooks: - id: autopep8 - repo: https://github.com/pycqa/isort From 61986c256de55c66b21a5b79ab4a1e3fd1fea3d3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 20:15:35 +0000 Subject: [PATCH 05/36] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/PyCQA/flake8: 7.0.0 → 7.1.0](https://github.com/PyCQA/flake8/compare/7.0.0...7.1.0) - [github.com/hhatto/autopep8: v2.1.1 → v2.3.1](https://github.com/hhatto/autopep8/compare/v2.1.1...v2.3.1) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e5258d2d..5610d84e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,11 +7,11 @@ repos: - id: check-yaml - id: check-merge-conflict - repo: https://github.com/PyCQA/flake8 - rev: 7.0.0 + rev: 7.1.0 hooks: - id: flake8 - repo: https://github.com/hhatto/autopep8 - rev: 'v2.1.1' + rev: 'v2.3.1' hooks: - id: autopep8 - repo: https://github.com/pycqa/isort From c3919e970bdba7fa84d0784618322bd0a2ae8d02 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Wed, 12 Jun 2024 21:14:51 -0700 Subject: [PATCH 06/36] remove relative import from example-create-item.py --- examples/item_creation/example-create-item.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/examples/item_creation/example-create-item.py b/examples/item_creation/example-create-item.py index 5bfb2dba..372bde79 100644 --- a/examples/item_creation/example-create-item.py +++ b/examples/item_creation/example-create-item.py @@ -1,12 +1,10 @@ -from pyonepassword import OP +from pyonepassword import OP, logging from pyonepassword.api.object_types import OPLoginItem -from ..do_signin import do_signin - if __name__ == "__main__": # see README.md for sign-in process - op: OP = do_signin() - + logger = logging.console_debug_logger("example-create-item") + op: OP = OP(logger=logger) title = "Example Login Item" username = "test_username" great_password = "really-great-password" From c2715605069b02f75500035f6c4b605ac66714a7 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Wed, 12 Jun 2024 21:18:32 -0700 Subject: [PATCH 07/36] add serialize() method to OPNewItemMixin --- pyonepassword/op_items/_new_item.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyonepassword/op_items/_new_item.py b/pyonepassword/op_items/_new_item.py index fa93d78b..7b198072 100644 --- a/pyonepassword/op_items/_new_item.py +++ b/pyonepassword/op_items/_new_item.py @@ -247,6 +247,10 @@ def secure_tempfile(self, encoding="utf8") -> str: self._copy_template(temp.name, template_dest_dir) return temp.name + def serialize(self, indent=None) -> str: + json_str = json.dumps(self, indent=indent) + return json_str + def supports_passwords(self) -> bool: """ Whether passwords are applicable items of this type From 95edefd57e949cc4d64ffad81082afe38d02e56d Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Wed, 12 Jun 2024 21:22:10 -0700 Subject: [PATCH 08/36] remove secure_tempfile() method from OPNewItemMixin --- pyonepassword/op_items/_new_item.py | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/pyonepassword/op_items/_new_item.py b/pyonepassword/op_items/_new_item.py index 7b198072..a1a86496 100644 --- a/pyonepassword/op_items/_new_item.py +++ b/pyonepassword/op_items/_new_item.py @@ -1,7 +1,6 @@ import json import os import shutil -import tempfile from pathlib import Path from typing import Dict, List, Optional @@ -219,34 +218,6 @@ def __init__(self, title: str, fields: List[OPItemField] = [], sections: List[OP super().__init__(*args) self._temp_files: List[str] = [] - def secure_tempfile(self, encoding="utf8") -> str: - """ - Serialize this item object to a secure temp file for use during 'op item create' - - The temporary file is deleted when this object goes out of scope - - Parameters - ---------- - encoding: str, optional - Encoding to use when serializing to file. Defaults to "utf-8" - - Returns - ------- - temp.name: str - The name of the temporary file - """ - temp = tempfile.NamedTemporaryFile( - mode="w", delete=False, encoding=encoding) - self._temp_files.append(temp.name) - json.dump(self, temp) - temp.close() - template_dest_dir = os.environ.get(TEMPLATE_COPY_DST_ENV_VAR, None) - if template_dest_dir: - # _copy_template() does no error handling - # only call if we were given a template copy destination - self._copy_template(temp.name, template_dest_dir) - return temp.name - def serialize(self, indent=None) -> str: json_str = json.dumps(self, indent=indent) return json_str From ca3a3b20dd93d34e8d1bdbc5a4f57c55acb4fca9 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Wed, 12 Jun 2024 21:23:56 -0700 Subject: [PATCH 09/36] remove _copy_template() method from OPNewItemMixin --- pyonepassword/op_items/_new_item.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/pyonepassword/op_items/_new_item.py b/pyonepassword/op_items/_new_item.py index a1a86496..ca7948ba 100644 --- a/pyonepassword/op_items/_new_item.py +++ b/pyonepassword/op_items/_new_item.py @@ -1,7 +1,5 @@ import json import os -import shutil -from pathlib import Path from typing import Dict, List, Optional from ..py_op_exceptions import OPInvalidItemException @@ -232,20 +230,6 @@ def supports_passwords(self) -> bool: """ return self.PASSWORDS_SUPPORTED - def _copy_template(self, template_src, template_dest_dir): - """ - Optionally make a backup copy of the new item template - if PYOP_NEW_ITEM_TEMPLATE_CP_DST environment variable is set - for debugging/troubleshooting - - This method intentionally does minimal error handling. It should only be called - for troublehooting purposes and any errors creating the destination or copying the source - should be fatal errors - """ - template_dest_dir = Path(template_dest_dir) - template_dest_dir.mkdir(parents=True, exist_ok=True) - shutil.copy2(template_src, template_dest_dir) - def __del__(self): # if we blow up during object initialization From 656f4e5e8951283719c8ee84b53cb8e0991ba2e6 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Wed, 12 Jun 2024 21:24:30 -0700 Subject: [PATCH 10/36] remove __del__() method from OPNewItemMixin --- pyonepassword/op_items/_new_item.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/pyonepassword/op_items/_new_item.py b/pyonepassword/op_items/_new_item.py index ca7948ba..0e7b13f0 100644 --- a/pyonepassword/op_items/_new_item.py +++ b/pyonepassword/op_items/_new_item.py @@ -1,5 +1,4 @@ import json -import os from typing import Dict, List, Optional from ..py_op_exceptions import OPInvalidItemException @@ -229,15 +228,3 @@ def supports_passwords(self) -> bool: password_supported: bool """ return self.PASSWORDS_SUPPORTED - - def __del__(self): - - # if we blow up during object initialization - # _temp_files may not exist, so check first - if hasattr(self, "_temp_files"): - while self._temp_files: - t = self._temp_files.pop() - try: - os.unlink(t) - except FileNotFoundError: - continue From ba695f52c39c8115117321a6555e68fbf3554739 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Wed, 12 Jun 2024 21:25:34 -0700 Subject: [PATCH 11/36] add 'encoding=' to _OPArgv.item_generic_argv() --- pyonepassword/_op_cli_argv.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pyonepassword/_op_cli_argv.py b/pyonepassword/_op_cli_argv.py index 0a4e536b..7687cc79 100644 --- a/pyonepassword/_op_cli_argv.py +++ b/pyonepassword/_op_cli_argv.py @@ -127,7 +127,8 @@ def document_delete_argv(cls, def item_generic_argv(cls, op_exe: str, subcommands: Optional[Union[str, List[str]]], - sub_cmd_args: Optional[List[str]] = None): + sub_cmd_args: Optional[List[str]] = None, + encoding="utf-8"): args = [] global_args = ["--format", "json"] if sub_cmd_args: @@ -136,7 +137,8 @@ def item_generic_argv(cls, "item", args, subcommands=subcommands, - global_args=global_args) + global_args=global_args, + encoding=encoding) return argv @classmethod From 53c2376ed5733883a7ee95b72f5c21e61a6cd124 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Wed, 12 Jun 2024 21:26:50 -0700 Subject: [PATCH 12/36] refactor _OPArgv.item_create_argv() to not require item object or secure tempfile --- pyonepassword/_op_cli_argv.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/pyonepassword/_op_cli_argv.py b/pyonepassword/_op_cli_argv.py index 7687cc79..621863eb 100644 --- a/pyonepassword/_op_cli_argv.py +++ b/pyonepassword/_op_cli_argv.py @@ -3,7 +3,6 @@ from ._field_assignment import FIELD_TYPE_MAP, OPFieldTypeEnum from ._svc_account import OPSvcAcctSupportCode, OPSvcAcctSupportRegistry -from .op_items._new_item import OPNewItemMixin from .op_items.password_recipe import OPPasswordRecipe from .string import RedactedString @@ -376,25 +375,20 @@ def account_forget_argv(cls, op_exe, account): # pragma: no coverage @classmethod def item_create_argv(cls, op_exe, - item: OPNewItemMixin, password_recipe: Optional[OPPasswordRecipe] = None, vault: Optional[str] = None, encoding="utf-8"): """ op item create --template ./new_item.json --vault "Test Data" --generate-password=20,letters,digits --dry-run --format json """ - template_filename = item.secure_tempfile( - encoding=encoding) - - item_create_args = ["--template", template_filename] - + item_create_args = [] if password_recipe: # '--password-recipe' requires an '=' unlike other option/argument pairs item_create_args.append(f"--generate-password={password_recipe}") if vault: item_create_args.extend(["--vault", vault]) argv = cls.item_generic_argv( - op_exe, "create", sub_cmd_args=item_create_args) + op_exe, "create", sub_cmd_args=item_create_args, encoding=encoding) return argv @classmethod From c7ad1009b6e9aedb846897f2415700e917dfb942 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Wed, 12 Jun 2024 21:28:25 -0700 Subject: [PATCH 13/36] type hint item object in _OPCommandInterface.item_create() --- pyonepassword/_op_commands.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyonepassword/_op_commands.py b/pyonepassword/_op_commands.py index 48cabfe3..2f389771 100644 --- a/pyonepassword/_op_commands.py +++ b/pyonepassword/_op_commands.py @@ -24,6 +24,7 @@ OPSvcAcctCommandNotSupportedException ) from .account import OPAccount, OPAccountList +from .op_items._new_item import OPNewItemMixin from .op_items.password_recipe import OPPasswordRecipe from .py_op_exceptions import ( OPAuthenticationException, @@ -796,7 +797,7 @@ def _item_list(self, categories=[], include_archive=False, tags=[], vault=None, raise OPItemListException.from_opexception(e) return output - def _item_create(self, item, vault, password_recipe, decode="utf-8"): + def _item_create(self, item: OPNewItemMixin, vault, password_recipe, decode="utf-8"): argv = self._item_create_argv(item, password_recipe, vault) try: output = self._run_with_auth_check( From a3aa7db8a0d25284fcbf914950728ab8e8fb1665 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Thu, 13 Jun 2024 22:06:51 -0700 Subject: [PATCH 14/36] refactor _OPCommandInterface._item_create() to pass item JSON over stdin --- pyonepassword/_op_commands.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pyonepassword/_op_commands.py b/pyonepassword/_op_commands.py index 2f389771..fceaf687 100644 --- a/pyonepassword/_op_commands.py +++ b/pyonepassword/_op_commands.py @@ -798,10 +798,11 @@ def _item_list(self, categories=[], include_archive=False, tags=[], vault=None, return output def _item_create(self, item: OPNewItemMixin, vault, password_recipe, decode="utf-8"): - argv = self._item_create_argv(item, password_recipe, vault) + item_json = item.serialize(indent=2) + argv = self._item_create_argv(password_recipe, vault) try: output = self._run_with_auth_check( - self.op_path, self._account_identifier, argv, capture_stdout=True, decode=decode) + self.op_path, self._account_identifier, argv, capture_stdout=True, input=item_json, decode=decode) except OPCmdFailedException as e: raise OPItemCreateException.from_opexception(e) @@ -985,10 +986,10 @@ def _vault_list_argv(self, group_name_or_id=None, user_name_or_id=None): self.op_path, group_name_or_id=group_name_or_id, user_name_or_id=user_name_or_id) return vault_list_argv - def _item_create_argv(self, item, password_recipe, vault): + def _item_create_argv(self, password_recipe, vault): vault_arg = vault if vault else self.vault item_create_argv = _OPArgv.item_create_argv( - self.op_path, item, password_recipe=password_recipe, vault=vault_arg + self.op_path, password_recipe=password_recipe, vault=vault_arg ) return item_create_argv From 2dd538da272b69f5413f33780a1e7a52cab0fdfb Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Thu, 13 Jun 2024 22:12:51 -0700 Subject: [PATCH 15/36] remove tests involving OPNewItemMixin.secure_tempfile() --- tests/new_item/test_new_database_item.py | 48 ------------------------ tests/new_item/test_new_login_item.py | 47 ----------------------- 2 files changed, 95 deletions(-) diff --git a/tests/new_item/test_new_database_item.py b/tests/new_item/test_new_database_item.py index d1653d4a..5b330e99 100644 --- a/tests/new_item/test_new_database_item.py +++ b/tests/new_item/test_new_database_item.py @@ -1,6 +1,5 @@ from __future__ import annotations -import os from typing import TYPE_CHECKING, Any, Dict, List from pyonepassword.api.object_types import OPDatabaseItemTemplate @@ -607,53 +606,6 @@ def test_new_database_item_100(valid_data: ValidData): assert database_template.options is None -def test_new_database_item_temp_file_010(): - """ - Create: - - An OPDatabaseItemTemplate object - - request a secure temp file with the object serialized as JSON - - release the new object - Verify: - - the temp file exists - - the temp file has been deleted when the object is released - """ - username = "test_username" - title = "Test Database Item" - - database_template = OPDatabaseItemTemplate(title, username) - temp_file_path = database_template.secure_tempfile() - assert os.path.isfile(temp_file_path) - - database_template = None - assert not os.path.exists(temp_file_path) - - -def test_new_database_item_temp_file_020(): - """ - Create: - - An OPDatabaseItemTemplate object - - request a secure temp file with the object serialized as JSON - - delete the temp file from under the object - - release the object - Verify: - - the temp file exists - - no exception is raised when object is released - """ - username = "test_username" - title = "Test Database Item" - - database_template = OPDatabaseItemTemplate(title, username) - temp_file_path = database_template.secure_tempfile() - assert os.path.isfile(temp_file_path) - - # dirty trick; this shouldn't happen. But we need to be robust against it anyway - os.remove(temp_file_path) - try: - database_template = None - except Exception as e: - assert False, f"new_login = None raised an exception {e}" - - def test_new_database_item_tags_010(valid_data: ValidData): """ Create: diff --git a/tests/new_item/test_new_login_item.py b/tests/new_item/test_new_login_item.py index e9e55657..1d3596f1 100644 --- a/tests/new_item/test_new_login_item.py +++ b/tests/new_item/test_new_login_item.py @@ -1,6 +1,5 @@ from __future__ import annotations -import os from typing import TYPE_CHECKING import pytest @@ -390,52 +389,6 @@ def test_new_login_item_12(valid_data: ValidData): OPLoginItemTemplate(title, username, sections=sections) -def test_new_login_item_13(): - """ - Create: - - An OPLoginItemTemplate object - - request a secure temp file with the object serialized as JSON - - release the new object - Verify: - - the temp file exists - - the temp file has been deleted when the object is released - """ - username = "test_username" - title = "Test Login Item" - - new_login = OPLoginItemTemplate(title, username) - temp_file_path = new_login.secure_tempfile() - assert os.path.isfile(temp_file_path) - new_login = None - assert not os.path.exists(temp_file_path) - - -def test_new_login_item_14(): - """ - Create: - - An OPLoginItemTemplate object - - request a secure temp file with the object serialized as JSON - - delete the temp file from under the object - - release the object - Verify: - - the temp file exists - - no exception is raised when object is released - """ - username = "test_username" - title = "Test Login Item" - - new_login = OPLoginItemTemplate(title, username) - temp_file_path = new_login.secure_tempfile() - assert os.path.isfile(temp_file_path) - - # dirty trick; this shouldn't happen. But we need to be robust against it anyway - os.remove(temp_file_path) - try: - new_login = None - except Exception as e: - assert False, f"new_login = None raised an exception {e}" - - def test_new_login_item_15(): """ Create: From cbaa5ed2b23f946f1da2b30d434303395c01d6a8 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Thu, 13 Jun 2024 22:17:33 -0700 Subject: [PATCH 16/36] remove instance variable tracking tempfiles when creating new item --- pyonepassword/op_items/_new_item.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyonepassword/op_items/_new_item.py b/pyonepassword/op_items/_new_item.py index 0e7b13f0..0f68b625 100644 --- a/pyonepassword/op_items/_new_item.py +++ b/pyonepassword/op_items/_new_item.py @@ -213,7 +213,6 @@ def __init__(self, title: str, fields: List[OPItemField] = [], sections: List[OP # Satisfy mypy: Too many arguments for "__init__" of "object" args = [template_dict] super().__init__(*args) - self._temp_files: List[str] = [] def serialize(self, indent=None) -> str: json_str = json.dumps(self, indent=indent) From 90ac97f868c6db52b88dd0fb6ac05034cab900fe Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Thu, 11 Jul 2024 21:17:03 -0700 Subject: [PATCH 17/36] remove "nopep8" directive --- pyonepassword/_op_commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyonepassword/_op_commands.py b/pyonepassword/_op_commands.py index fceaf687..79e28bc0 100644 --- a/pyonepassword/_op_commands.py +++ b/pyonepassword/_op_commands.py @@ -132,7 +132,7 @@ def __init__(self, # if a password is passed in but existing_auth is required, caller may be confused: # - intentionally passed in incompatible options # - possibly has OP_SERVICE_ACCOUNT_TOKEN set accidentally - msg = f"Password argument passed but EXISTING_AUTH_REQD flag is set. flag source: {auth_pref_source}" # nopep8 + msg = f"Password argument passed but EXISTING_AUTH_REQD flag is set. flag source: {auth_pref_source}" self.logger.error(msg) raise OPAuthenticationException(msg) From 54d639388eed122d6e35630fefb1be7e11e32593 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Thu, 11 Jul 2024 21:18:24 -0700 Subject: [PATCH 18/36] remove remaining "nopep8" directives --- pyonepassword/_py_op_deprecation.py | 4 ++-- pyonepassword/_svc_account.py | 6 +++--- pyonepassword/pyonepassword.py | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pyonepassword/_py_op_deprecation.py b/pyonepassword/_py_op_deprecation.py index 6be9d473..a94b6dd5 100644 --- a/pyonepassword/_py_op_deprecation.py +++ b/pyonepassword/_py_op_deprecation.py @@ -94,12 +94,12 @@ def _rename_kwargs(func_name: str, kwargs: Dict[str, Any], kwarg_aliases: Dict[s if old_kwarg in kwargs: if new_kwarg in kwargs: raise TypeError( - f"{func_name} received both {old_kwarg} and {new_kwarg} as arguments!" # nopep8 + f"{func_name} received both {old_kwarg} and {new_kwarg} as arguments!" f" {old_kwarg} is deprecated, use {new_kwarg} instead." ) warnings.warn( message=( - f"`{old_kwarg}` is deprecated as an argument to `{func_name}`; use" # nopep8 + f"`{old_kwarg}` is deprecated as an argument to `{func_name}`; use" f" `{new_kwarg}` instead." ), category=DeprecationWarning, diff --git a/pyonepassword/_svc_account.py b/pyonepassword/_svc_account.py index 61fd679e..55a3152c 100644 --- a/pyonepassword/_svc_account.py +++ b/pyonepassword/_svc_account.py @@ -179,7 +179,7 @@ def command_supported(self, _argv: List[str]) -> OPSvcAcctSupportCode: # then command is not supported _cmd_not_found = command is not None and cmd_spec is None if (cmd_spec and not cmd_dict) or _cmd_not_found: - _support_msg = f"Command or subcommand not supported: [{command} {' '.join(subcommands)}]" # nopep8 + _support_msg = f"Command or subcommand not supported: [{command} {' '.join(subcommands)}]" _support_code = SVC_ACCT_CMD_NOT_SUPPORTED if cmd_dict and _support_code == _SVC_ACCT_CMD_NOT_VALIDATED: @@ -220,10 +220,10 @@ def command_supported(self, _argv: List[str]) -> OPSvcAcctSupportCode: if _support_code == SVC_ACCT_INCOMPAT_OPTIONS: _support_msg = "" if not required_opt_satified: - _support_msg += f"Required options not provided: [{','.join(list(reqd_opt_diff))}]" # nopep8 + _support_msg += f"Required options not provided: [{','.join(list(reqd_opt_diff))}]" if not prohibited_opt_satisfied: - _support_msg += f" Prohibited options found: [{','.join(list(prohib_opt_diff))}]" # nopep8 + _support_msg += f" Prohibited options found: [{','.join(list(prohib_opt_diff))}]" _support_msg = _support_msg.lstrip() diff --git a/pyonepassword/pyonepassword.py b/pyonepassword/pyonepassword.py index d9d43382..840651fa 100644 --- a/pyonepassword/pyonepassword.py +++ b/pyonepassword/pyonepassword.py @@ -2099,7 +2099,7 @@ def _validate_item_field_exists(self, msg = f"No field found '{field_label}' that lacks a section" raise OPFieldNotFoundException(msg) else: - msg = f"Section '{section_label}', field '{field_label}' not found" # nopep8 + msg = f"Section '{section_label}', field '{field_label}' not found" raise OPFieldNotFoundException(msg) return field From fbe971a8856b3efd53fbb7d611c03141d574c0c3 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Thu, 25 Jul 2024 20:36:36 -0700 Subject: [PATCH 19/36] suppress mypy error for incompatible overridden method signature --- pyonepassword/op_items/_item_list.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyonepassword/op_items/_item_list.py b/pyonepassword/op_items/_item_list.py index 6e8f3378..7c01fff7 100644 --- a/pyonepassword/op_items/_item_list.py +++ b/pyonepassword/op_items/_item_list.py @@ -25,7 +25,7 @@ def serialize(self, indent=None) -> str: json_str = json.dumps(self, indent=indent) return json_str - def sort(self): + def sort(self): # type: ignore[override] # we really want to be sorted by title, since that's the most # human friendly (mainly for troubleshooting) # but in the case if title collisions, this is still non-deterministic From 751b95136bf71db34cb277744ac41f489575d33e Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Thu, 25 Jul 2024 20:47:31 -0700 Subject: [PATCH 20/36] print some status from docker testing scripts --- docker_testing/build.sh | 5 +++++ docker_testing/clean.sh | 5 +++++ docker_testing/run.sh | 3 +++ 3 files changed, 13 insertions(+) diff --git a/docker_testing/build.sh b/docker_testing/build.sh index 7e6f5e8c..62c0b5c7 100755 --- a/docker_testing/build.sh +++ b/docker_testing/build.sh @@ -2,7 +2,12 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +echo "Building..." + docker buildx build "$SCRIPT_DIR"/docker/ -f "$SCRIPT_DIR"/docker/py39.Dockerfile -t docker_py39 || exit docker buildx build "$SCRIPT_DIR"/docker/ -f "$SCRIPT_DIR"/docker/py310.Dockerfile -t docker_py310 || exit docker buildx build "$SCRIPT_DIR"/docker/ -f "$SCRIPT_DIR"/docker/py311.Dockerfile -t docker_py311 || exit docker buildx build "$SCRIPT_DIR"/docker/ -f "$SCRIPT_DIR"/docker/py312.Dockerfile -t docker_py312 || exit + +echo "...done" +echo "" diff --git a/docker_testing/clean.sh b/docker_testing/clean.sh index 64787cfa..d6fd02f2 100755 --- a/docker_testing/clean.sh +++ b/docker_testing/clean.sh @@ -2,5 +2,10 @@ # keep unused docker image names so we can ensure they get removed # this should not be an error +echo "Cleaning..." +echo "removing docker images" docker image rm docker_py38 docker_py39 docker_py310 docker_py311 docker_py312 +echo "removing .tox-docker" rm -rf .tox-docker +echo "...done" +echo "" diff --git a/docker_testing/run.sh b/docker_testing/run.sh index a744abe6..3a75fe98 100755 --- a/docker_testing/run.sh +++ b/docker_testing/run.sh @@ -22,6 +22,7 @@ trap handle_sig INT ret=0 +echo "Running docker tests..." docker run --rm -it -v "$(pwd):/usr/src/testdir" docker_py39 /test.sh "$@" ret="$(($?+ret))" docker run --rm -it -v "$(pwd):/usr/src/testdir" docker_py310 /test.sh "$@" @@ -31,4 +32,6 @@ ret="$(($?+ret))" docker run --rm -it -v "$(pwd):/usr/src/testdir" docker_py312 /test.sh "$@" ret="$(($?+ret))" +echo "...done" +echo "" exit "$ret" From 2bf323c11ab985d27e85e817c225b7b887ffca9f Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Sat, 3 Aug 2024 19:21:39 -0700 Subject: [PATCH 21/36] fix typos in README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4f3b4b64..b7eb9a01 100644 --- a/README.md +++ b/README.md @@ -354,14 +354,14 @@ def main(): For details on creating new items in a 1Password vault, see [item-creation.md](docs/item-creation.md) -Also see the examles in [examples/item_creation](examples/item_creation/) +Also see the examples in [examples/item_creation](examples/item_creation/) ### Item Editing For details on editing existing items in a 1Password vault, see [item-editing.md](docs/item-editing.md) -Also see the examles in [examples/item_editing](examples/item_editing/) +Also see the examples in [examples/item_editing](examples/item_editing/) ### Document Editing From 9a41b2a90cf121a40a67d23d566d75262fe5599a Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Sat, 3 Aug 2024 19:22:00 -0700 Subject: [PATCH 22/36] fix typo in comment in setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index d247eb86..65328e4c 100644 --- a/setup.py +++ b/setup.py @@ -43,7 +43,7 @@ def validate_readme(): # links on PyPI should have absolute URLs # this awful regex looks for [any text](any url), making sure there's no 'http:' # in the url part -# it then inserts https://github.com/zcutlip/pyonepassword/blobl/main/ +# it then inserts https://github.com/zcutlip/pyonepassword/blob/main/ # after between the '(' and the relative URL # believe it or not this also works with directories such as examples/item_editing/ # Github redirects from blob/main/ to tree/main/ in this case From e1f137c5ca3ab4fffadca4869d1525841733e89c Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Sat, 3 Aug 2024 19:44:21 -0700 Subject: [PATCH 23/36] OPNewSecureNoteItem kwargs default to None --- ipython_snippets/item_creation.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ipython_snippets/item_creation.py b/ipython_snippets/item_creation.py index fc310eac..7fd166ad 100644 --- a/ipython_snippets/item_creation.py +++ b/ipython_snippets/item_creation.py @@ -1,4 +1,4 @@ -from typing import List +from typing import List, Optional from pyonepassword import OP # noqa: F401 from pyonepassword.api.object_types import ( @@ -23,8 +23,8 @@ class OPNewSecureNoteItem(OPNewItemMixin, OPSecureNoteItem): def __init__(self, title: str, note_text: str, - fields: List[OPItemField] = [], - sections: List[OPSection] = []): + fields: Optional[List[OPItemField]] = None, + sections: Optional[List[OPSection]] = None): if sections is None: # pragma: no coverage sections = [] From c72d3681439755ca4e2e82eba50318b9770bc719 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Sat, 3 Aug 2024 20:27:21 -0700 Subject: [PATCH 24/36] Revert "fix typos in README" This reverts commit 2bf323c11ab985d27e85e817c225b7b887ffca9f. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b7eb9a01..4f3b4b64 100644 --- a/README.md +++ b/README.md @@ -354,14 +354,14 @@ def main(): For details on creating new items in a 1Password vault, see [item-creation.md](docs/item-creation.md) -Also see the examples in [examples/item_creation](examples/item_creation/) +Also see the examles in [examples/item_creation](examples/item_creation/) ### Item Editing For details on editing existing items in a 1Password vault, see [item-editing.md](docs/item-editing.md) -Also see the examples in [examples/item_editing](examples/item_editing/) +Also see the examles in [examples/item_editing](examples/item_editing/) ### Document Editing From eb3f470d570a69a3aa92604c9df2a7f667fbb116 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Sat, 3 Aug 2024 20:28:39 -0700 Subject: [PATCH 25/36] fix typos in README template --- _readme_template.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_readme_template.md b/_readme_template.md index da4f1791..518fd863 100644 --- a/_readme_template.md +++ b/_readme_template.md @@ -354,14 +354,14 @@ def main(): For details on creating new items in a 1Password vault, see [item-creation.md](docs/item-creation.md) -Also see the examles in [examples/item_creation](examples/item_creation/) +Also see the examples in [examples/item_creation](examples/item_creation/) ### Item Editing For details on editing existing items in a 1Password vault, see [item-editing.md](docs/item-editing.md) -Also see the examles in [examples/item_editing](examples/item_editing/) +Also see the examples in [examples/item_editing](examples/item_editing/) ### Document Editing From f43edea92cac25f3feafbf90ccac36fea895babf Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Sat, 3 Aug 2024 20:29:47 -0700 Subject: [PATCH 26/36] add print statements to update_readme.py --- scripts/update_readme.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/update_readme.py b/scripts/update_readme.py index 2f70a5cc..b1da8911 100755 --- a/scripts/update_readme.py +++ b/scripts/update_readme.py @@ -45,11 +45,13 @@ def main(): readme_text = generate_readme_text(README_TEMPLATE) needs_update = check_readme(README, readme_text) if args.check: + print("README needs updating") return int(needs_update) if needs_update: with open(README, "w") as f: f.write(readme_text) + print("README updated") if __name__ == "__main__": From 88c1dc29523d1c16bb7283e5b0731cc3acf2c529 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Sat, 3 Aug 2024 20:30:04 -0700 Subject: [PATCH 27/36] regenerated README to fix typos --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4f3b4b64..b7eb9a01 100644 --- a/README.md +++ b/README.md @@ -354,14 +354,14 @@ def main(): For details on creating new items in a 1Password vault, see [item-creation.md](docs/item-creation.md) -Also see the examles in [examples/item_creation](examples/item_creation/) +Also see the examples in [examples/item_creation](examples/item_creation/) ### Item Editing For details on editing existing items in a 1Password vault, see [item-editing.md](docs/item-editing.md) -Also see the examles in [examples/item_editing](examples/item_editing/) +Also see the examples in [examples/item_editing](examples/item_editing/) ### Document Editing From 09a8ce4f59e90d0b1e2e618465be0c9bad7b30d3 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Sat, 3 Aug 2024 21:15:32 -0700 Subject: [PATCH 28/36] fix update_readmy.py print statement --- scripts/update_readme.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/update_readme.py b/scripts/update_readme.py index b1da8911..8f5cd7e7 100755 --- a/scripts/update_readme.py +++ b/scripts/update_readme.py @@ -45,7 +45,8 @@ def main(): readme_text = generate_readme_text(README_TEMPLATE) needs_update = check_readme(README, readme_text) if args.check: - print("README needs updating") + if needs_update: + print("README needs updating") return int(needs_update) if needs_update: From 0ead3421f4b18c9087075ee3cde13dbbfd649c73 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Sat, 3 Aug 2024 21:15:41 -0700 Subject: [PATCH 29/36] bump version to 5.0.1 --- pyonepassword/__about__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyonepassword/__about__.py b/pyonepassword/__about__.py index 7f187b48..bce3551c 100644 --- a/pyonepassword/__about__.py +++ b/pyonepassword/__about__.py @@ -1,5 +1,5 @@ __title__ = "pyonepassword" -__version__ = "5.0.1.dev0" +__version__ = "5.0.1" __summary__ = "A python API to query a 1Password account using the 'op' command-line tool" """ From bac4f58f5b681415e319481ed9241fdeaebcaa59 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Mon, 5 Aug 2024 19:35:23 -0700 Subject: [PATCH 30/36] regenerate README to reflect updated op CLI version support --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b7eb9a01..6a6940f3 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,9 @@ A Python API to sign into and query a 1Password account using the `op` command. ## Requirements - Python >= 3.9 -- 1Password command-line tool >= 2.24.0 - - Versions >= 2.19.0, < 2.24.0 supported but deprecated - - Versions < 2.19.0 are unsupported and an exception will be raised +- 1Password command-line tool >= 2.25.0 + - Versions >= 2.20.0, < 2.25.0 supported but deprecated + - Versions < 2.20.0 are unsupported and an exception will be raised - See [1Password Developer Documentation](https://developer.1password.com/docs/cli) - Internet connectivity to 1Password.com - The `op` command queries your online account, not your local vault From 982e93346ae23b0a562a9ed086273721bf86d914 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Mon, 5 Aug 2024 19:50:36 -0700 Subject: [PATCH 31/36] op version support - drop < 2.20.0 - deprecate < 2.25.0 --- pyonepassword/data/op_versions/version_support.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyonepassword/data/op_versions/version_support.json b/pyonepassword/data/op_versions/version_support.json index d1c51ef3..809e2907 100644 --- a/pyonepassword/data/op_versions/version_support.json +++ b/pyonepassword/data/op_versions/version_support.json @@ -3,8 +3,8 @@ "version": 1 }, "version-support":{ - "supported": "2.24.0", - "minimum": "2.19.0" + "supported": "2.25.0", + "minimum": "2.20.0" }, "feature-support": { "example-feature-service-accounts": "2.18.0" From b8383414aabb6a2c6ae3c495e5e4b17ca3b04473 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Mon, 5 Aug 2024 19:50:50 -0700 Subject: [PATCH 32/36] update CHANGELOG.md for 5.0.1 --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2cebabe..4fe333d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,23 @@ All notable changes to this project will be documented in this file. +## [5.0.1] 2024-08-03 + +### Fixed + +- Create new items via stdin to `op` command rather than reading from temp file + +### `op` CLI Version Support + +*Deprecated support* + +- `op` versions < 2.25.0 and >= 2.20.0 + +*Unsupported* + +- `op` versions < 2.20.0 + + ## [5.0.0] 2024-05-24 ### Added From f5b0104a83ab0af298a995aee8479bec252c4463 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Mon, 5 Aug 2024 20:03:15 -0700 Subject: [PATCH 33/36] op version support - drop < 2.21.0 - deprecate < 2.26.0 --- pyonepassword/data/op_versions/version_support.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyonepassword/data/op_versions/version_support.json b/pyonepassword/data/op_versions/version_support.json index 809e2907..bd725711 100644 --- a/pyonepassword/data/op_versions/version_support.json +++ b/pyonepassword/data/op_versions/version_support.json @@ -3,8 +3,8 @@ "version": 1 }, "version-support":{ - "supported": "2.25.0", - "minimum": "2.20.0" + "supported": "2.26.0", + "minimum": "2.21.0" }, "feature-support": { "example-feature-service-accounts": "2.18.0" From 8ff2f8e294de997c2d499d7ebeb7b092cd784795 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Mon, 5 Aug 2024 20:03:30 -0700 Subject: [PATCH 34/36] regenerate README to reflect updated op CLI version support --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6a6940f3..18353ba6 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,9 @@ A Python API to sign into and query a 1Password account using the `op` command. ## Requirements - Python >= 3.9 -- 1Password command-line tool >= 2.25.0 - - Versions >= 2.20.0, < 2.25.0 supported but deprecated - - Versions < 2.20.0 are unsupported and an exception will be raised +- 1Password command-line tool >= 2.26.0 + - Versions >= 2.21.0, < 2.26.0 supported but deprecated + - Versions < 2.21.0 are unsupported and an exception will be raised - See [1Password Developer Documentation](https://developer.1password.com/docs/cli) - Internet connectivity to 1Password.com - The `op` command queries your online account, not your local vault From dcc92848c3d4f09415ef77b1b9094cc85ef90498 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Mon, 5 Aug 2024 20:05:49 -0700 Subject: [PATCH 35/36] minor edits to CHANGELOG --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fe333d4..c29ad0b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,17 +6,17 @@ All notable changes to this project will be documented in this file. ### Fixed -- Create new items via stdin to `op` command rather than reading from temp file +- Create new items via stdin to `op` command rather than reading from temp file (gh-172) ### `op` CLI Version Support *Deprecated support* -- `op` versions < 2.25.0 and >= 2.20.0 +- `op` versions < 2.26.0 and >= 2.21.0 *Unsupported* -- `op` versions < 2.20.0 +- `op` versions < 2.21.0 ## [5.0.0] 2024-05-24 From eef13bc1d351272631916d9d4f843acad417d824 Mon Sep 17 00:00:00 2001 From: Zachary Cutlip Date: Mon, 5 Aug 2024 20:07:44 -0700 Subject: [PATCH 36/36] update CHANGELOG with references to gh-200 --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c29ad0b9..71cdcd2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,11 +12,11 @@ All notable changes to this project will be documented in this file. *Deprecated support* -- `op` versions < 2.26.0 and >= 2.21.0 +- `op` versions < 2.26.0 and >= 2.21.0 (gh-200) *Unsupported* -- `op` versions < 2.21.0 +- `op` versions < 2.21.0 (gh-200) ## [5.0.0] 2024-05-24