From 676b07e3e30375be88c7e9d190f086dd9b68be89 Mon Sep 17 00:00:00 2001 From: Alex Mueller Date: Mon, 16 Apr 2018 05:10:13 -0400 Subject: [PATCH] Implemented and tested CLI for multi-language support. To provide support for multiple languages (issue #37), I implemented a command line interface with several options related to languages, including an option to list all available languages and an option to automatically download subtitles for all available languages. --- Subtitle.cmd => bin/Subtitle.cmd | 2 +- .../Subtitles_In_English.sh | 2 +- .../Subtitles_In_English_for_nemo.sh | 2 +- bin/install.sh | 36 +++ bin/run.sh | 10 + bin/subtitle.sh | 4 + setup.py | 24 ++ subtitle-downloader.py | 134 --------- subtitle-downloader/__init__.py | 2 + subtitle-downloader/subtitle_downloader.py | 271 ++++++++++++++++++ subtitle.sh | 4 - tests/test_cli.py | 120 ++++++++ 12 files changed, 470 insertions(+), 141 deletions(-) rename Subtitle.cmd => bin/Subtitle.cmd (82%) rename Subtitles_In_English.sh => bin/Subtitles_In_English.sh (85%) mode change 100644 => 100755 rename Subtitles_In_English_for_nemo.sh => bin/Subtitles_In_English_for_nemo.sh (81%) mode change 100644 => 100755 create mode 100755 bin/install.sh create mode 100755 bin/run.sh create mode 100755 bin/subtitle.sh create mode 100644 setup.py delete mode 100755 subtitle-downloader.py create mode 100644 subtitle-downloader/__init__.py create mode 100755 subtitle-downloader/subtitle_downloader.py delete mode 100644 subtitle.sh create mode 100644 tests/test_cli.py diff --git a/Subtitle.cmd b/bin/Subtitle.cmd similarity index 82% rename from Subtitle.cmd rename to bin/Subtitle.cmd index 50fdbb1..7c65b90 100644 --- a/Subtitle.cmd +++ b/bin/Subtitle.cmd @@ -4,7 +4,7 @@ IF EXIST C:\Python34\ SET PATH=%PATH%;C:\Python34\ IF EXIST C:\Python27\ SET PATH=%PATH%;C:\Python27\ :my_loop IF %1=="" GOTO completed - python C:\subtitle-downloader.py %1 + python C:\subtitle_downloader.py %1 SHIFT GOTO my_loop :completed diff --git a/Subtitles_In_English.sh b/bin/Subtitles_In_English.sh old mode 100644 new mode 100755 similarity index 85% rename from Subtitles_In_English.sh rename to bin/Subtitles_In_English.sh index fa2632d..3979b7d --- a/Subtitles_In_English.sh +++ b/bin/Subtitles_In_English.sh @@ -3,7 +3,7 @@ IFS=" " for line in $NAUTILUS_SCRIPT_SELECTED_FILE_PATHS; do - full_path="/home/"$USER"/Desktop/"subtitle-downloader.py + full_path="/home/"$USER"/Desktop/"subtitle_downloader.py python $full_path $line notify-send $line done diff --git a/Subtitles_In_English_for_nemo.sh b/bin/Subtitles_In_English_for_nemo.sh old mode 100644 new mode 100755 similarity index 81% rename from Subtitles_In_English_for_nemo.sh rename to bin/Subtitles_In_English_for_nemo.sh index f6008b6..dcaaa6d --- a/Subtitles_In_English_for_nemo.sh +++ b/bin/Subtitles_In_English_for_nemo.sh @@ -3,7 +3,7 @@ IFS=" " for line in $NEMO_SCRIPT_SELECTED_FILE_PATHS; do - full_path="/home/"$USER"/Desktop/"subtitle-downloader.py + full_path="/home/"$USER"/Desktop/subtitle-downloader/"subtitle_downloader.py python $full_path $line notify-send $line done diff --git a/bin/install.sh b/bin/install.sh new file mode 100755 index 0000000..44afdea --- /dev/null +++ b/bin/install.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +# to be run in the same directory as "setup.py" + +# Must use this unless there is an official release +development_build() +{ + python3 -m venv env + source env/bin/activate + pip install --upgrade pip + pip install -e . + chmod +x bin/*.sh +} + +development_build_uninstall() +{ + rm -rf env/ subtitle-downloader.egg-info/ + pip uninstall . +} + +# Version to use if offical release ever happens +production_build() +{ + pip install subtitle-downloader +} + +if [ $1 = "uninstall" ]; then + development_build_uninstall + exit 0 +fi + +if [ $1 = "reinstall" ]; then + development_build_uninstall +fi + +development_build diff --git a/bin/run.sh b/bin/run.sh new file mode 100755 index 0000000..00daf52 --- /dev/null +++ b/bin/run.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# to be run in the same directory as "setup.py" + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +# Forward all arguments directly to the program itself. +# e.g. running "./bin/run.sh --list -v" is equivalent to +# "python subtitle-downloader/subtitle_downloader.py --list -v" +python $DIR/../subtitle-downloader/subtitle_downloader.py "$@" diff --git a/bin/subtitle.sh b/bin/subtitle.sh new file mode 100755 index 0000000..6148383 --- /dev/null +++ b/bin/subtitle.sh @@ -0,0 +1,4 @@ +for i in "$@" +do + python subtitle-downloader/subtitle_downloader.py "$i" +done diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..13f8c8d --- /dev/null +++ b/setup.py @@ -0,0 +1,24 @@ +"""Subtitle downloader.""" + + +from setuptools import setup + + +setup( + name='subtitle-downloader', + version='0.1.0', + packages=['subtitle-downloader'], + include_package_data=True, + install_requires=[ + "beautifulsoup4==4.6.0", + "bs4==0.0.1", + "certifi==2017.4.17", + "chardet==3.0.3", + "click==6.7", + "idna==2.5", + "lxml==3.8.0", + "requests==2.17.3", + "sh==1.12.14", + "urllib3==1.21.1" + ] +) diff --git a/subtitle-downloader.py b/subtitle-downloader.py deleted file mode 100755 index ff8695e..0000000 --- a/subtitle-downloader.py +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/env python -#------------------------------------------------------------------------------- -# Name : subtitle downloader -# Purpose : One step subtitle download -# -# Authors : manoj m j, arun shivaram p, Valentin Vetter, niroyb -# Edited by : Valentin Vetter -# Created : -# Copyright : (c) www.manojmj.com -# Licence : GPL v3 -# -# -#Edited for my using: Mohamed Hamza. -#------------------------------------------------------------------------------- - -# TODO: use another DB if subs are not found on subDB -import hashlib -import os -import shutil -import sys -import logging -import requests,time,re,zipfile -from bs4 import BeautifulSoup -PY_VERSION = sys.version_info[0] -if PY_VERSION == 2: - import urllib2 -if PY_VERSION == 3: - import urllib.request - - -def get_hash(file_path): - read_size = 64 * 1024 - with open(file_path, 'rb') as f: - data = f.read(read_size) - f.seek(-read_size, os.SEEK_END) - data += f.read(read_size) - return hashlib.md5(data).hexdigest() - - -def sub_downloader(file_path): - # Put the code in a try catch block in order to continue for other video files, if it fails during execution - try: - # Skip this file if it is not a video - root, extension = os.path.splitext(file_path) - if extension not in [".avi", ".mp4", ".mkv", ".mpg", ".mpeg", ".mov", ".rm", ".vob", ".wmv", ".flv", ".3gp",".3g2"]: - return - - if not os.path.exists(root + "en.srt"): - headers = {'User-Agent': 'SubDB/1.0 (subtitle-downloader/1.0; http://github.com/manojmj92/subtitle-downloader)'} - url = "http://api.thesubdb.com/?action=download&hash=" + get_hash(file_path) + "&language=en" - if PY_VERSION == 3: - req = urllib.request.Request(url, None, headers) - response = urllib.request.urlopen(req).read() - if PY_VERSION == 2: - req = urllib2.Request(url, '', headers) - response = urllib2.urlopen(req).read() - - with open(root + "en.srt", "wb") as subtitle: - subtitle.write(response) - logging.info("Subtitle successfully downloaded for " + file_path) - - except: - #download subs from subscene if not found in subdb - sub_downloader2(file_path, 'English') -def sub_downloader2(file_path, language): - try: - root, extension = os.path.splitext(file_path) - if extension not in [".avi", ".mp4", ".mkv", ".mpg", ".mpeg", ".mov", ".rm", ".vob", ".wmv", ".flv", ".3gp",".3g2"]: - return - - j=-1 - root2=root - for idx, char in enumerate(reversed(root)): - if(char == "\\" or char =="/"): - j = len(root)-1 - idx - break - root=root2[j+1:] - root2=root2[:j+1] - r=requests.get("http://subscene.com/subtitles/release?q="+root); - soup=BeautifulSoup(r.content,"lxml") - atags=soup.find_all("a") - href="" - for i in range(0,len(atags)): - spans=atags[i].find_all("span") - if(len(spans)==2 and spans[0].get_text().strip()==language and spans[1].get_text().strip()==root): - href=atags[i].get("href").strip() - print(href) - if(len(href)>0): - r=requests.get("http://subscene.com"+href); - soup=BeautifulSoup(r.content,"lxml") - lin=soup.find_all('a',attrs={'id':'downloadButton'})[0].get("href") - print('this lint', lin) - r=requests.get("http://subscene.com"+lin); - soup=BeautifulSoup(r.content,"lxml") - subfile=open(root2+" {}.zip".format(language), 'wb') - for chunk in r.iter_content(100000): - subfile.write(chunk) - subfile.close() - time.sleep(1) - zip_=zipfile.ZipFile(root2+" {}.zip".format(language)) #Naming zip is not recommended renamed it to zip_ (Following PEP 8 convention) - zip_.extractall(root2) #Naming it as zip would overwrite built-in function zip - zip_.close() - os_.unlink(root2+" {}.zip".format(language)) - shutil.move(root2+zip.namelist()[0], os.path.join(root2, root + " {}.srt".format(language))) - except: - #Ignore exception and continue - print("Error in fetching subtitle for " + file_path) - print("Error", sys.exc_info()) - logging.error("Error in fetching subtitle for " + file_path + str(sys.exc_info())) - - -def main(): - root, _ = os.path.splitext(sys.argv[0]) - logging.basicConfig(filename=root + '.log', level=logging.INFO) - logging.info("Started with params " + str(sys.argv)) - - # if len(sys.argv) == 1: - # print("This program requires at least one parameter") - # sys.exit(1) - - for path in sys.argv: - if os.path.isdir(path): - # Iterate the root directory recursively using os.walk and for each video file present get the subtitle - for dir_path, _, file_names in os.walk(path): - for filename in file_names: - file_path = os.path.join(dir_path, filename) - sub_downloader(file_path) - sub_downloader2(file_path, 'Arabic') - else: - sub_downloader(path) - sub_downloader2(path, 'Arabic') - -if __name__ == '__main__': - main() diff --git a/subtitle-downloader/__init__.py b/subtitle-downloader/__init__.py new file mode 100644 index 0000000..5eb66e7 --- /dev/null +++ b/subtitle-downloader/__init__.py @@ -0,0 +1,2 @@ +"""Subtitle downloader package initialization.""" +from subtitle_downloader import * diff --git a/subtitle-downloader/subtitle_downloader.py b/subtitle-downloader/subtitle_downloader.py new file mode 100755 index 0000000..a5b92ba --- /dev/null +++ b/subtitle-downloader/subtitle_downloader.py @@ -0,0 +1,271 @@ +#!/usr/bin/env python +#------------------------------------------------------------------------------- +# Name : subtitle downloader +# Purpose : One step subtitle download +# +# Authors : manoj m j, arun shivaram p, Valentin Vetter, niroyb +# Edited by : Valentin Vetter +# Created : +# Copyright : (c) www.manojmj.com +# Licence : GPL v3 +# +# +# Edited for my using: Mohamed Hamza. +# Modified for multi-language support: Alex Mueller +#------------------------------------------------------------------------------- + +import zipfile +import time +import sys +import shutil +import re +import os +import logging +import json +import hashlib +import glob + +import click +import requests +from bs4 import BeautifulSoup +PY_VERSION = sys.version_info[0] +if PY_VERSION == 2: + import urllib2 +if PY_VERSION == 3: + import urllib.request + +# List of ISO 639-1 two-letter language codes +# (reference: https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) +# This list is *very* incomplete. If your language doesn't appear here, +# feel free to add to the list. The program should still function as expected. +LANGUAGE_CODES = { + "Arabic": "ar", + "Chinese": "zh", + "Danish": "da", + "Dutch": "nl", + "English": "en", + "Esperanto": "eo", # Yes, I included Esperanto... just in case. + "Finnish": "fi", + "French": "fr", + "German": "de", + "Greek": "el", + "Hebrew": "he", + "Hindi": "hi", + "Irish": "ga", + "Italian": "it", + "Japanese": "ja", + "Korean": "ko", + "Mongolian": "mn", + "Norwegian": "no", + "Persian": "fa", + "Polish": "pl", + "Portuguese": "pt", + "Russian": "ru", + "Spanish": "es", + "Swedish": "sv", + "Thai": "th", + "Urdu": "ur", + "Vietnamese": "vi", + "Welsh": "cy", + "Yiddish": "yi", + "Zulu": "zu" +} + +# List of video file extensions this program supports +VIDEO_EXTENSIONS = [ + ".avi", ".mp4", ".mkv", ".mpg", + ".mpeg", ".mov", ".rm", ".vob", + ".wmv", ".flv", ".3gp",".3g2" +] + + +def get_hash(file_path): + """Return the hash of the video file.""" + read_size = 64 * 1024 + with open(file_path, 'rb') as f: + data = f.read(read_size) + f.seek(-read_size, os.SEEK_END) + data += f.read(read_size) + return hashlib.md5(data).hexdigest() + + +def get_from_subdb(file_path, language, verbose=False): + """Download subtitles from subdb.""" + try: + # Skip this file if it is not a video + root, extension = os.path.splitext(file_path) + if extension not in VIDEO_EXTENSIONS: + if verbose: + print(file_path + " is not a video file. Skipping.") + return + + language_code = LANGUAGE_CODES[language] + filename = root + language_code + ".srt" + + if not os.path.exists(filename): + headers = {'User-Agent': 'SubDB/1.0 (subtitle-downloader/1.0; http://github.com/manojmj92/subtitle-downloader)'} + url = "http://api.thesubdb.com/?action=download&hash=" + get_hash(file_path) + "&language=" + language_code + if PY_VERSION == 3: + req = urllib.request.Request(url, None, headers) + response = urllib.request.urlopen(req).read() + if PY_VERSION == 2: + req = urllib2.Request(url, '', headers) + response = urllib2.urlopen(req).read() + + with open(filename, "wb") as subtitle: + subtitle.write(response) + if verbose: + print(language + " subtitles successfully downloaded for " + file_path) + # logging.info(language + " subtitles successfully downloaded for " + file_path) + + except: + if verbose: + print(language + " subtitles not found for " + file_path + " in subdb") + + +def get_from_subscene(file_path, language): + """Download subtitles from subscene.""" + try: + root, extension = os.path.splitext(file_path) + if extension not in VIDEO_EXTENSIONS: + return + + j=-1 + root2=root + for idx, char in enumerate(reversed(root)): + if(char == "\\" or char =="/"): + j = len(root)-1 - idx + break + root=root2[j+1:] + root2=root2[:j+1] + print("language is " + language) + r=requests.get("http://subscene.com/subtitles/release?q="+root); + soup=BeautifulSoup(r.content,"lxml") + atags=soup.find_all("a") + href="" + for i in range(0,len(atags)): + spans=atags[i].find_all("span") + if(len(spans)==2 and spans[0].get_text().strip()==language and spans[1].get_text().strip()==root): + href=atags[i].get("href").strip() + print(href) + if(len(href)>0): + r=requests.get("http://subscene.com"+href); + soup=BeautifulSoup(r.content,"lxml") + lin=soup.find_all('a',attrs={'id':'downloadButton'})[0].get("href") + print('this lint', lin) + r=requests.get("http://subscene.com"+lin); + soup=BeautifulSoup(r.content,"lxml") + subfile=open(root2+" {}.zip".format(language), 'wb') + for chunk in r.iter_content(100000): + subfile.write(chunk) + subfile.close() + time.sleep(1) + zip_=zipfile.ZipFile(root2+" {}.zip".format(language)) #Naming zip is not recommended renamed it to zip_ (Following PEP 8 convention) + zip_.extractall(root2) #Naming it as zip would overwrite built-in function zip + zip_.close() + os_.unlink(root2+" {}.zip".format(language)) + shutil.move(root2+zip.namelist()[0], os.path.join(root2, root + " {}.srt".format(language))) + except: + #Ignore exception and continue + print("Error in fetching subtitle for " + file_path) + print("Error", sys.exc_info()) + logging.error("Error in fetching subtitle for " + file_path + str(sys.exc_info())) + + +@click.command(context_settings=dict(max_content_width=80)) +@click.option("download_all", "--all", "-a", is_flag=True, + help="""Download subtitles in all available languages (nullifies '-i' or '-l') + + If subtitles cannot be found in a particular language, the download for that language will fail silently unless the verbose option is specified. + \b + + """) +@click.option("--iso", "-i", default="en", + help="""Specify the ISO 639-1 two-letter code that corresponds to your chosen subtitle language. For example, you would specify '--iso=fr' if you wanted French subtitles. + + If both the ISO value and the language name are specified, the ISO value takes priority. + \b + + """) +@click.option("--language", "-l", default="English", + help="""Select subtitle language by name (default: English). + \b + + """) +@click.option("list_languages", "--list", is_flag=True, + help="""List all available language name / ISO 639-1 code pairs and exit. + \b + + """) +@click.option("--verbose", "-v", is_flag=True, + help="""If this flag is on, console output will indicate which downloads were / were not successful. + \b + + """) +@click.argument("input_path", type=click.Path(), default="./") +def main(download_all, iso, language, list_languages, verbose, input_path): + """General purpose subtitle downloader.""" + if list_languages: + # JSON for pretty-printing + print(json.dumps(LANGUAGE_CODES, indent=4)) + sys.exit(0) + + # glob.glob doesn't like square brackets in the file path + if '[' in input_path or ']' in input_path: + click.echo("Error: file path must not contain square brackets.") + sys.exit(0) + + # root, _ = os.path.splitext(input_path) + # logging.basicConfig(filename=root + '.log', level=logging.INFO) + # logging.info("Started with params " + str(sys.argv)) + + languages = [] + if download_all: + langauges = LANGUAGE_CODES.keys() + else: + if iso not in LANGUAGE_CODES.values(): + click.echo("Error: language code '" + iso + "' is unsupported.\n\nFor" + "a list of valid language codes, use the '--list' option.") + click.echo("") + click.echo("To add support for this language, open the python \n" + "source code and modify LANGUAGE_CODES accordingly.") + sys.exit(1) + + if language not in LANGUAGE_CODES: + click.echo("Error: language '" + language + "' is unsupported.\n\nFor" + "a list of supported languages, use the '--list' option.") + click.echo("") + click.echo("To add support for this language, open the python \n" + "source code and modify LANGUAGE_CODES accordingly.") + sys.exit(1) + + # if both iso and language options are present, iso takes priority. + if LANGUAGE_CODES[language] != iso: + if verbose: + click.echo("Language name '" + language + "' does not match" + " ISO 639-1 language code '" + iso + "'.") + + # the dictionary is mapped by language name, so we have to reverse it + # to get the language name based on the code entered. This approach is + # slightly inefficient, but I personally find it much more readable. + language = dict(map(reversed, LANGUAGE_CODES.items()))[iso] + if verbose: + click.echo("Proceeding with language '" + language + "'" + " (the language specified by the code).") + + languages.append(language) + + for lang in languages: + if os.path.isdir(input_path): + files = [] + for extension in VIDEO_EXTENSIONS: + for file in glob.glob(input_path + "*" + extension): + files.append(file) + for file in files: + get_from_subdb(file, lang, verbose=verbose) + else: + get_from_subdb(input_path, lang, verbose=verbose) + + +if __name__ == '__main__': + main() diff --git a/subtitle.sh b/subtitle.sh deleted file mode 100644 index a3fc106..0000000 --- a/subtitle.sh +++ /dev/null @@ -1,4 +0,0 @@ -for i in "$@" -do - python path/to/the/repo/subtitle-downloader.py "$i" -done diff --git a/tests/test_cli.py b/tests/test_cli.py new file mode 100644 index 0000000..26ed375 --- /dev/null +++ b/tests/test_cli.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python +""" +Test module for subtitle-downloader command line interface. + +Designed to be run in the same directory as "setup.py" +""" + +import subprocess +import os +import io +import glob + +import sh + +# syntactic sugar for (somewhat) shorter filenames in the list definition +# modify accordingly for local testing +DLDS = "/home/alecastle/Downloads/" +VIDEO_FILES = [ + "12 Monkeys (1995)/12Monkeys.mp4", # test movie title starting with numbers + "Brazil (1985)/Brazil.avi", # test .avi format, as opposed to .mp4 + "Hackers/Hackers.mp4", # vanilla test, no tricks + "Monsters Inc (2001)/MonstersInc.mkv" # test .mkv format, as opposed to .mp4 + "The Room (2003)/TheRoom.mp4", # test spaces/parentheses in directory name + "War Games (1983) [1080p]/WarGames.mkv", # test square brackets in directory name (should fail) + "Wings of Desire (1987) 720p BRrip_sujaidr (pimprg)/Wings of Desire (1987) 720p BRrip_sujaidr (pimprg).mkv" + # test really long directory/file name with multiple special characters + # also, this movie has a spoken language of German +] +for index, file in enumerate(VIDEO_FILES): + VIDEO_FILES[index] = os.path.join(DLDS, file) + +# directory contains multiple movies +# again, modify accordingly for local testing +VIDEO_DIRECTORY = "/home/alecastle/Desktop/Movies/" + +# reinstall development build for a fresh testing environment +sh.Command("./bin/install.sh")("reinstall") + +def test_run_script(): + print("test_run_script") + + executable = os.path.realpath("../bin/run.sh") + + sh.Command(executable) # should do nothing; default behavior is to look in + # the current directory, which in this case should + # not have any video files. + sh.Command(executable)("--help") # should print help message. + + buf1 = io.StringIO() + sh.Command(executable)("--list", _out=buf1) # should list available languages. + + buf2 = io.StringIO() + sh.Command(executable)("--list", "-a", + _out=buf2) # output should be the same as previous command + # since --list is a flag, it should take priority. + assert buf1.getvalue() == buf2.getvalue(), "--list is a flag; it should override any other functionality" + + for file in VIDEO_FILES: + sh.Command(executable)("-i", "en", file) # should work except for square brackets in directory + + sh.Command(executable)("-v", VIDEO_DIRECTORY) # test video directory + + # gather a list of subtitle files created before removing them + sub_files = glob.glob(VIDEO_DIRECTORY + "*.srt") + sh.Command("rm")("-rf", sub_files) + + # change directories to the path containing the video files + current_path = os.path.realpath(__file__) + sh.cd(os.path.abspath(VIDEO_DIRECTORY)) + + # run vanilla command and ensure that the result is the same as before + subprocess.run([executable]) + sub_files2 = glob.glob(VIDEO_DIRECTORY + "*.srt") + + try: + assert sub_files == sub_files2 + except AssertionError: + print("Error: given no arguments, script should search the current directory") + sh.cd(os.path.dirname(current_path)) + + +def test_python_script(): + print("test_python_script") + + executable = os.path.realpath("subtitle-downloader/subtitle_downloader.py") + + # should try all languages and print whether each download was successful + # -a option should override language specifications, even invalid ones + for file in VIDEO_FILES: + sh.python(executable, "--verbose", "-a", "--language", "Engrish", file) + + sh.python(executable, VIDEO_DIRECTORY) # test video directory + + # gather a list of subtitle files created before removing them + sub_files = glob.glob(VIDEO_DIRECTORY + "*.srt") + sh.Command("rm")("-rf", sub_files) + + # change directories to the path containing the video files + current_path = os.path.realpath(__file__) + sh.cd(os.path.abspath(VIDEO_DIRECTORY)) + + # run vanilla command and ensure that the result is the same as before + sh.python(executable) + sub_files2 = glob.glob(VIDEO_DIRECTORY + "*.srt") + + try: + assert sub_files == sub_files2 + except AssertionError: + print("Error: given no arguments, script should search the current directory") + + sh.cd(os.path.dirname(current_path)) + + +def main(): + # comment out as needed + test_python_script() + test_run_script() + +if __name__ == "__main__": + main() \ No newline at end of file