Skip to content

Commit

Permalink
Merge pull request #102 from arrrlo/develop
Browse files Browse the repository at this point in the history
hotfix/terminal-outputs-progressbar
  • Loading branch information
arrrlo authored Mar 17, 2021
2 parents 94b5351 + 80a4fcd commit b5c7b5c
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 25 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
/Google_Images_Search.egg-info/
/build/
/dist/
/google_images_search/
/tests/__pycache__/
/.DS_Store
.venv
/tests/test_my.py
/google_images_search/__pycache__/
/dwnld/
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ python:
- 3.9

script:
- pip install .
- pip3 install .
- pip3 install pytest
- pip list
- pytest -vvv

deploy:
Expand Down
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Changelog

## 1.3.7

### Fixed in 1.3.7

- Handling CLI exception when api key and cx are not provided
- Handling PIL open and rgb convert exception

## Added in 1.3.7

- Curses terminal progress is now started and ended using context (with statement)
- CLI also uses contextual progress
- Better progress output in CLI overall

## 1.3.6

### Fixed in 1.3.6
Expand Down
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,16 +162,28 @@ gis = GoogleImagesSearch('your_dev_api_key', 'your_project_cx', validate_images=

## [Inserting custom progressbar function](#progressbar)

By default, progressbar is not enabled.
Only in CLI progressbar is enabled by default using [Curses library](https://docs.python.org/3/howto/curses.html).
In a programmatic mode it can be enabled in two ways:
- using contextual mode (Curses)
- using your custom progressbar function

```python
from google_images_search import GoogleImagesSearch

# using your custom progressbar function
def my_progressbar(url, progress):
print(url + ' ' + progress + '%')

gis = GoogleImagesSearch(
'your_dev_api_key', 'your_project_cx', progressbar_fn=my_progressbar
)
_search_params = {...}
gis.search(search_params=_search_params)

# using contextual mode (Curses)
with GoogleImagesSearch('your_dev_api_key', 'your_project_cx') as gis:
_search_params = {...}
gis.search(search_params=_search_params)
...
```

Expand Down
27 changes: 19 additions & 8 deletions google_images_search/cli.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import click
import googleapiclient

from .fetch_resize_save import FetchResizeSave
from .google_api import GoogleBackendException
from .fetch_resize_save import FetchResizeSave, __version__


@click.group()
@click.pass_context
@click.option('-k', '--developer_key', help='Developer API key')
@click.option('-c', '--custom_search_cx', help='Custom Search CX')
def cli(ctx, developer_key, custom_search_cx):
click.echo()
click.secho(f'GOOGLE IMAGES SEARCH {__version__}', fg='yellow')
click.echo()

ctx.obj = {
'object': FetchResizeSave(
developer_key, custom_search_cx, progress=True
developer_key, custom_search_cx
)
}

Expand Down Expand Up @@ -65,14 +70,17 @@ def search(ctx, query, num, safe, filetype, imagetype, imagesize,
'imgDominantColor': dominantcolor
}

click.clear()

try:
ctx.obj['object'].search(search_params, download_path,
width, height, custom_file_name)
gis = ctx.obj['object']

with gis:
gis.search(search_params, download_path,
width, height, custom_file_name)

if ctx.obj['object'].results():
for image in ctx.obj['object'].results():
results = ctx.obj['object'].results()

if results:
for image in results:
click.echo(image.url)
if image.path:
click.secho(image.path, fg='blue')
Expand All @@ -87,4 +95,7 @@ def search(ctx, query, num, safe, filetype, imagetype, imagesize,
except GoogleBackendException:
click.secho('Error occurred trying to fetch '
'images from Google. Please try again.', fg='red')

except googleapiclient.errors.HttpError as e:
click.secho(f'Google reported an error: {str(e)}', fg='red')
return
64 changes: 52 additions & 12 deletions google_images_search/fetch_resize_save.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
import curses
import requests
import threading
from PIL import Image
from PIL import Image, UnidentifiedImageError
from resizeimage import resizeimage, imageexceptions

from .meta import __version__
from .google_api import GoogleCustomSearch


Expand All @@ -15,7 +16,7 @@ class FetchResizeSave(object):
"""Class with resizing and downloading logic"""

def __init__(self, developer_key, custom_search_cx,
progressbar_fn=None, progress=False, validate_images=True):
progressbar_fn=None, validate_images=True):

# initialise google api
self._google_custom_search = GoogleCustomSearch(
Expand All @@ -42,12 +43,41 @@ def __init__(self, developer_key, custom_search_cx,
if progressbar_fn:
# user inserted progressbar fn
self._progress = True
else:
if progress:
# initialise internal progressbar
self._progress = True
self._stdscr = curses.initscr()
self._report_progress = self.__report_progress

def __enter__(self):
"""Emtering a terminal window setup
:return: self
"""

self._report_progress = self.__report_progress
self._progress = True

# set terminal screen
self._stdscr = curses.initscr()
self._stdscr.keypad(True)
curses.cbreak()
curses.noecho()

# show terminal header information
self._stdscr.addstr(0, 0, f'GOOGLE IMAGES SEARCH {__version__}')

return self

def __exit__(self, exc_type, exc_val, exc_tb):
"""Exiting terminal window and putting all back as it was
:param exc_type:
:param exc_val:
:param exc_tb:
:return:
"""

self._progress = False

# reverse all as it was
self._stdscr.keypad(False)
curses.nocbreak()
curses.echo()
curses.endwin()

def _set_data(self, search_params=None, path_to_dir=False,
width=None, height=None, cache_discovery=True):
Expand Down Expand Up @@ -259,7 +289,10 @@ def increment_naming(dir_list, name, number=0):
for chunk in self.get_raw_data(url):
f.write(chunk)

Image.open(path_to_image).convert('RGB').save(path_to_image, 'jpeg')
try:
Image.open(path_to_image).convert('RGB').save(path_to_image, 'jpeg')
except UnidentifiedImageError:
pass

return path_to_image

Expand Down Expand Up @@ -294,7 +327,14 @@ def resize(path_to_image, width, height):

fd_img = open(path_to_image, 'rb')
img = Image.open(fd_img)
img = resizeimage.resize_cover(img, [int(width), int(height)])

try:
img = resizeimage.resize_cover(img, [int(width), int(height)])
except resizeimage.ImageSizeError:
# error resizing an image
# image is probably too small
pass

img.save(path_to_image, img.format)
fd_img.close()

Expand All @@ -306,10 +346,10 @@ def __report_progress(self, url, progress):
"""

self._stdscr.addstr(
self._terminal_lines[url], 0, "Downloading file: {0}".format(url)
self._terminal_lines[url] + 2, 0, "Downloading file: {0}".format(url)
)
self._stdscr.addstr(
self._terminal_lines[url] + 1, 0,
self._terminal_lines[url] + 3, 0,
"Progress: [{1:100}] {0}%".format(progress, "#" * progress)
)
self._stdscr.refresh()
Expand Down
1 change: 1 addition & 0 deletions google_images_search/meta.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__ = '1.3.7'
9 changes: 8 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
from setuptools import setup


Expand All @@ -6,9 +7,15 @@ def readme():
return f.read()


def version():
with open(os.path.join('.', 'google_images_search', 'meta.py')) as f:
contents = f.read()
return contents.split('__version__ = ')[1].strip()[1:-1]


setup(
name='Google Images Search',
version="1.3.6",
version=version(),

description='Search for image using Google Custom Search '
'API and resize & crop the image afterwords',
Expand Down
2 changes: 1 addition & 1 deletion tests/test_fetch_resize_save.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def test_init(self):
self.assertEqual(self._frs._progress, False)

frs = FetchResizeSave(self._api_key, self._api_cx,
progressbar_fn=lambda x, y: None, progress=True)
progressbar_fn=lambda x, y: None)

self.assertEqual(frs._chunk_sizes, {})
self.assertEqual(frs._terminal_lines, {})
Expand Down

0 comments on commit b5c7b5c

Please sign in to comment.