diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml new file mode 100644 index 0000000..2c2c20b --- /dev/null +++ b/.github/workflows/pylint.yml @@ -0,0 +1,24 @@ +name: Pylint + +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.10", "3.11", "3.12"] + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pylint + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + - name: Analysing the code with pylint + run: | + pylint $(git ls-files '*.py') diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml new file mode 100644 index 0000000..fca6f97 --- /dev/null +++ b/.github/workflows/python-app.yml @@ -0,0 +1,35 @@ +# This workflow will install Python dependencies, run tests and lint with a single version of Python +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python + +name: Flake8 and pytest + +on: [push] + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up Python 3.10 + uses: actions/setup-python@v3 + with: + python-version: "3.10" + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install flake8 pytest + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + - name: Lint with flake8 + run: | + # stop the build if there are Python syntax errors or undefined names + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + - name: Test with pytest + run: | + pytest diff --git a/clipea/__init__.py b/clipea/__init__.py index e9930aa..e4d96a5 100644 --- a/clipea/__init__.py +++ b/clipea/__init__.py @@ -1,5 +1,5 @@ """Clipea application -📎🟢 Like Clippy but for the CLI. A blazing fast AI helper for your command line +📎🟢 Like Clippy but for the CLI. A blazing fast AI helper for your command line """ import os from clipea import utils, cli diff --git a/clipea/__main__.py b/clipea/__main__.py index b9a2dd2..eef29d9 100644 --- a/clipea/__main__.py +++ b/clipea/__main__.py @@ -6,11 +6,16 @@ def clipea_main() -> None: + """ + Main function for the Clipea. It checks if the "llm" dependency is installed + and then prompts the user for input. It then routes the user's input + to the appropriate command in the router. + """ if shutil.which("llm") is None: sys.exit('Error: dependency "llm" not found. Run "clipea setup" to install') - USER_PROMPT = " ".join(sys.argv[1:]) - router.commands_router(USER_PROMPT) + user_prompt = " ".join(sys.argv[1:]) + router.commands_router(user_prompt) if __name__ == "__main__": diff --git a/clipea/clipea_llm.py b/clipea/clipea_llm.py index 144e4d2..b096f71 100644 --- a/clipea/clipea_llm.py +++ b/clipea/clipea_llm.py @@ -57,7 +57,7 @@ def process_command(): current_command = command[2:new_line_pos] else: current_command = command[2:] - command = command[new_line_pos + 1 :] + command = command[new_line_pos + 1:] if output_file is not None: buffer += current_command + os.linesep @@ -87,5 +87,5 @@ def process_command(): if output_file: utils.write_to_file( output_file, - ';\ '.join(buffer.rstrip(os.linesep).split(os.linesep)) + os.linesep, + ';'.join(buffer.rstrip(os.linesep).split(os.linesep)) + os.linesep, ) diff --git a/clipea/commands.py b/clipea/commands.py index e049666..fb349bb 100644 --- a/clipea/commands.py +++ b/clipea/commands.py @@ -8,7 +8,7 @@ def setup(): """Checks if `llm` has an openai key and prompt to change it or create one""" - import llm.cli + import llm.cli # pylint: disable=import-outside-toplevel should_setup = True path = llm.cli.user_dir() / "keys.json" @@ -22,7 +22,8 @@ def setup(): ) else: print("An OpenAI key is already set-up, proceed if you want to change it.") - llm.cli.keys_set() + # Trigger key setting (llm uses Click) + llm.cli.keys_set() # pylint: disable=no-value-for-parameter def clipea_execute_prompt(user_prompt: str): @@ -40,17 +41,17 @@ def clipea_execute_prompt(user_prompt: str): Args: user_prompt (str): user command input """ - from clipea import clipea_llm - from llm import Model, Response + from clipea import clipea_llm # pylint: disable=import-outside-toplevel + from llm import Model, Response # pylint: disable=import-outside-toplevel - llm_name:str = '' + llm_name: str = '' if user_prompt.startswith('4 '): user_prompt = user_prompt[2:] llm_name = 'gpt-4' try: model: Model = clipea_llm.init_llm(llm_name) - except Exception as e: + except Exception as e: # pylint: disable=broad-exception-caught sys.exit(str(e)) user_data: str = cli.get_input() @@ -64,7 +65,7 @@ def clipea_execute_prompt(user_prompt: str): def alias(): """Gives zsh's alias (automatic command buffering) commands to the user""" shell: str = ENV["shell"] - if shell == "zsh" or shell == "-zsh": + if shell in ('zsh', '-zsh'): command: str = f"alias '??'='source {CLIPEA_DIR}/clipea.zsh'" user_prompt: str = f"Append this line to my {shell} startup file, \ watching out for quotes and escaping, then explain how to manually source it: {command}" diff --git a/clipea/utils.py b/clipea/utils.py index 1fe54f2..5e7701a 100644 --- a/clipea/utils.py +++ b/clipea/utils.py @@ -16,6 +16,7 @@ def anystr_force_str(value: AnyStr) -> str: """ return value.decode("utf-8") if isinstance(value, bytes) else value + def read_file(file_path: str) -> str: """Reads a file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..ded3a7a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +llm==0.12 +setuptools==68.0.0 diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 0000000..a89906a --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,9 @@ +"""Utils tests +""" +from clipea import utils + + +def test_anystr_force_str(): + """Basic test for anystr_force_str()""" + assert utils.anystr_force_str(b'hello') == 'hello' + assert utils.anystr_force_str('hello') == 'hello'