Coverage for pass_import/formats/cli.py: 100%
43 statements
« prev ^ index » next coverage.py v7.4.3, created at 2024-02-26 12:11 +0000
« prev ^ index » next coverage.py v7.4.3, created at 2024-02-26 12:11 +0000
1# -*- encoding: utf-8 -*-
2# pass import - Passwords importer swiss army knife
3# Copyright (C) 2017-2024 Alexandre PUJOL <alexandre@pujol.io>.
4#
6import os
7import shutil
8from abc import abstractmethod
9from subprocess import PIPE, Popen # nosec
11from pass_import.core import Cap
12from pass_import.errors import PMError
13from pass_import.manager import PasswordExporter, PasswordImporter
16class CLI(PasswordImporter, PasswordExporter):
17 """Base class for CLI based importer and exporter."""
18 cap = Cap.IMPORT | Cap.EXPORT
19 format = 'cli'
20 command = ''
22 def __init__(self, prefix=None, settings=None):
23 self._binary = shutil.which(self.command)
24 if self._binary is None:
25 raise PMError(f"{self.command} is required.") # pragma: no cover
27 self.env = dict(**os.environ)
28 super().__init__(prefix, settings)
30 def _setenv(self, var, env=None, value=None):
31 """Add var in the environment variables dictionary."""
32 if env is None:
33 env = var
34 if env in os.environ:
35 self.env[var] = os.environ[env]
36 if value is not None:
37 self.env[var] = value
39 def _call(self, command, data=None, nline=True):
40 """Call to a command."""
41 if isinstance(data, bytes):
42 nline = False
43 with Popen(command, universal_newlines=nline, env=self.env, stdin=PIPE,
44 stdout=PIPE, stderr=PIPE, shell=False) as process:
45 (stdout, stderr) = process.communicate(data)
46 res = process.wait()
47 return res, stdout, stderr
49 def _command(self, arg, data=None, nline=True):
50 """Call to the password manager cli command."""
51 command = [self._binary]
52 command.extend(arg)
53 res, stdout, stderr = self._call(command, data, nline)
54 if res:
55 raise PMError(f"{stderr} {stdout}")
56 return stdout
58 def exist(self):
59 """Nothing to do."""
60 return True
62 @abstractmethod
63 def parse(self):
64 """Parse the password manager repository and retrieve passwords."""
66 @abstractmethod
67 def insert(self, entry):
68 """Insert a password entry into the password repository."""