Skip to content

Commit

Permalink
Gracefully handle Pyperclip exception when the user uses an OS with n…
Browse files Browse the repository at this point in the history
…o clipboard available (#68)

* Handle pyperclip exception

* Additional check

* Don't wait when clipboard is not used

* Update Dockerfile

* Update Dockerfile entrypoint

* fix test

* Fix coverage
  • Loading branch information
gabfl authored Jan 19, 2022
1 parent 3ad3e4c commit 9325113
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 7 deletions.
6 changes: 5 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ RUN git clone https://github.com/sqlcipher/sqlcipher.git \
RUN wget https://bootstrap.pypa.io/get-pip.py \
&& python3 get-pip.py

# RUN git clone -b pyperclip-except https://github.com/gabfl/vault.git \
# && cd vault \
# && pip3 install .

RUN pip3 install pyvault

ENTRYPOINT [ "vault" ]
ENTRYPOINT [ "/bin/bash", "-c", "sqlcipher --version && pip3 freeze | grep pyvault && vault" ]
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Vault 2.x requires `sqlcipher` to be installed on your machine.

### MacOS

On MacOS, you can install `sqlcipher`` with [brew](https://brew.sh/):
On MacOS, you can install `sqlcipher` with [brew](https://brew.sh/):
```bash
brew install sqlcipher

Expand All @@ -54,7 +54,7 @@ vault
On Ubuntu/Debian, you can install `sqlcipher` with apt:
```bash
sudo apt update
sudo apt install -y gcc python3-dev libsqlcipher-dev
sudo apt install -y gcc python3-dev libsqlcipher-dev xclip
```

Then install the vault:
Expand Down Expand Up @@ -86,7 +86,7 @@ docker run -v ~/.vault:/root/.vault -ti gabfl/vault
git clone https://github.com/gabfl/vault && cd vault

# Installation
python3 setup.py install
pip3 install .

# Run setup
vault
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

setup(
name='pyvault',
version='2.4.1',
version='2.4.2',
description='Python password manager',
long_description=long_description,
author='Gabriel Bordeaux',
Expand Down
12 changes: 12 additions & 0 deletions src/unittest/views/test_clipboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ def test_is_changed_2(self, patched):
clipboard.clipboard_signature = clipboard.get_signature('some string')
self.assertTrue(clipboard.is_changed())

def test_is_changed_3(self):
clipboard.clipboard_signature = ''
self.assertIsNone(clipboard.is_changed())

def test_getSignature(self):
self.assertEqual(clipboard.get_signature(
'some string'), '61d034473102d7dac305902770471fd50f4c5b26f6831a56dd90b5184b3c30fc')
Expand All @@ -42,6 +46,7 @@ def test_getSignature(self):
def test_wait(self, patched, patched2):
patched.return_value = 'some string'
patched2.return_value = 'some string'
clipboard.clipboard_signature = clipboard.get_signature('some string')
# Ensure we have a short wait time
global_scope['conf'].update('clipboardTTL', '1')

Expand All @@ -53,12 +58,19 @@ def test_wait(self, patched, patched2):
def test_wait_2(self, patched, patched2):
patched.return_value = 'some other string'
patched2.return_value = 'some string'
clipboard.clipboard_signature = clipboard.get_signature('some string')
# Ensure we have a short wait time
global_scope['conf'].update('clipboardTTL', '1')

self.assertIsNone(clipboard.wait())
self.assertEqual(clipboard.clipboard_signature, '')

def test_wait_3(self):
# Case when we have no clipboard_signature because
# pyperclip is not available
self.assertEqual(clipboard.clipboard_signature, '')
self.assertIsNone(clipboard.wait())

@patch.object(pyperclip, 'copy')
@patch.object(pyperclip, 'paste')
def test_erase(self, patched, patched2):
Expand Down
12 changes: 10 additions & 2 deletions src/views/clipboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ def copy(to_copy, name='password', erase=False):
print('* Nothing to copy!')
return False

pyperclip.copy(to_copy)
try:
pyperclip.copy(to_copy)
except pyperclip.PyperclipException:
print('* Error: could not find a copy/paste mechanism for your system')
return False

if not erase:
print('* The %s has been copied to the clipboard.' % (name))
Expand All @@ -34,7 +38,8 @@ def is_changed():
Returns `True` if the clipboard content has changed
"""

return clipboard_signature != get_signature(pyperclip.paste())
if clipboard_signature:
return clipboard_signature != get_signature(pyperclip.paste())


def get_signature(item):
Expand All @@ -51,6 +56,9 @@ def wait():
Wait X seconds and erase the clipboard
"""

if not clipboard_signature:
return None

print("* Clipboard will be erased in %s seconds" %
(global_scope['conf'].clipboardTTL))

Expand Down

0 comments on commit 9325113

Please sign in to comment.