├── requirements.txt ├── .flake8 ├── .isort.cfg ├── Makefile ├── run_pylint.py ├── .editorconfig ├── .github └── workflows │ └── test-plugin-installation.yml ├── helpers.sh ├── pyproject.toml ├── .pre-commit-config.yaml ├── .coveragerc ├── helpers.bat ├── LICENSE ├── README.md ├── .sourcery.yaml ├── .gitignore ├── src └── auto_gpt_todoist_plugin │ ├── client.py │ └── __init__.py └── pylintrc /requirements.txt: -------------------------------------------------------------------------------- 1 | black 2 | isort 3 | flake8 4 | pylint 5 | abstract-singleton 6 | wheel 7 | setuptools 8 | build 9 | twine 10 | todoist-api-python -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 88 3 | extend-ignore = E203 4 | exclude = 5 | .tox, 6 | __pycache__, 7 | *.pyc, 8 | .env 9 | venv/* 10 | .venv/* 11 | reports/* 12 | dist/* 13 | -------------------------------------------------------------------------------- /.isort.cfg: -------------------------------------------------------------------------------- 1 | [settings] 2 | profile = black 3 | multi_line_output = 3 4 | include_trailing_comma = true 5 | force_grid_wrap = 0 6 | use_parentheses = true 7 | ensure_newline_before_comments = true 8 | line_length = 88 9 | sections = FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER 10 | skip = .tox,__pycache__,*.pyc,venv*/*,reports,venv,env,node_modules,.env,.venv,dist 11 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ifeq ($(OS),Windows_NT) 2 | os := win 3 | SCRIPT_EXT := .bat 4 | SHELL_CMD := cmd /C 5 | else 6 | os := nix 7 | SCRIPT_EXT := .sh 8 | SHELL_CMD := bash 9 | endif 10 | 11 | helpers = @$(SHELL_CMD) helpers$(SCRIPT_EXT) $1 12 | 13 | clean qa style: helpers$(SCRIPT_EXT) 14 | 15 | clean: 16 | $(call helpers,clean) 17 | 18 | qa: 19 | $(call helpers,qa) 20 | 21 | style: 22 | $(call helpers,style) 23 | 24 | .PHONY: clean qa style -------------------------------------------------------------------------------- /run_pylint.py: -------------------------------------------------------------------------------- 1 | """ 2 | https://stackoverflow.com/questions/49100806/ 3 | pylint-and-subprocess-run-returning-exit-status-28 4 | """ 5 | import subprocess 6 | 7 | cmd = " pylint src\\**\\*" 8 | try: 9 | subprocComplete = subprocess.run( 10 | cmd, shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE 11 | ) 12 | print(subprocComplete.stdout.decode("utf-8")) 13 | except subprocess.CalledProcessError as err: 14 | print(err.output.decode("utf-8")) 15 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Top-most EditorConfig file 2 | root = true 3 | 4 | # Set default charset 5 | [*] 6 | charset = utf-8 7 | 8 | # Use black formatter for python files 9 | [*.py] 10 | profile = black 11 | 12 | # Set defaults for windows and batch filess 13 | [*.bat] 14 | end_of_line = crlf 15 | indent_style = space 16 | indent_size = 2 17 | 18 | # Set defaults for shell scripts 19 | [*.sh] 20 | end_of_line = lf 21 | trim_trailing_whitespace = true 22 | insert_final_newline = false 23 | 24 | # Set defaults for Makefiles 25 | [Makefile] 26 | end_of_line = lf 27 | indent_style = tab 28 | indent_size = 4 29 | trim_trailing_whitespace = true 30 | insert_final_newline = true -------------------------------------------------------------------------------- /.github/workflows/test-plugin-installation.yml: -------------------------------------------------------------------------------- 1 | name: Test installation of plugin against the PR 2 | on: 3 | push: 4 | branches: [ master ] 5 | pull_request: 6 | branches: [ master ] 7 | 8 | jobs: 9 | test-plugin-installation: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Install Kurtosis 13 | run: | 14 | echo "deb [trusted=yes] https://apt.fury.io/kurtosis-tech/ /" | sudo tee /etc/apt/sources.list.d/kurtosis.list 15 | sudo apt update 16 | sudo apt install kurtosis-cli 17 | - name: Install plugins 18 | run: | 19 | set -euo pipefail 20 | kurtosis run github.com/kurtosis-tech/autogpt-package '{"OPENAI_API_KEY": "test", "ALLOWLISTED_PLUGINS": "AutoGPTTodoistPlugin", "__plugin_branch_to_use": '\"${{ github.head_ref}}\"', "__plugin_repo_to_use":'\"${{ github.event.pull_request.head.repo.full_name }}\"'}' 21 | -------------------------------------------------------------------------------- /helpers.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | clean() { 6 | # Remove build artifacts and temporary files 7 | rm -rf {build,dist,__pycache__,*.egg-info,**/*.egg-info,*.pyc,**/*.pyc,reports} 2>/dev/null || true 8 | } 9 | 10 | qa() { 11 | # Run static analysis tools 12 | if command -v flake8 >/dev/null 2>&1; then 13 | flake8 . 14 | fi 15 | 16 | python run_pylint.py 17 | } 18 | 19 | style() { 20 | # Format code 21 | isort . 22 | black --exclude=".*/*(dist|venv|.venv|test-results)/*.*" . 23 | } 24 | 25 | case "$1" in 26 | clean) 27 | echo Removing build artifacts and temporary files... 28 | clean 29 | ;; 30 | qa) 31 | echo Running static analysis tools... 32 | qa 33 | ;; 34 | style) 35 | echo Running code formatters... 36 | style 37 | ;; 38 | *) 39 | echo "Usage: $0 [clean|qa|style]" 40 | exit 1 41 | ;; 42 | esac 43 | 44 | printf 'Done!\n\n' 45 | exit 0 -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["hatchling"] 3 | build-backend = "hatchling.build" 4 | 5 | [project] 6 | name = "auto_gpt_plugin_template" 7 | version = "0.0.2" 8 | authors = [ 9 | { name="Torantulino", email="34168009+BillSchumacher@users.noreply.github.com" }, 10 | ] 11 | description = "The template plugin for Auto-GPT." 12 | readme = "README.md" 13 | requires-python = ">=3.8" 14 | classifiers = [ 15 | "Programming Language :: Python :: 3", 16 | "License :: OSI Approved :: MIT License", 17 | "Operating System :: OS Independent", 18 | ] 19 | dependencies = ["abstract-singleton"] 20 | 21 | [project.urls] 22 | "Homepage" = "https://github.com/Torantulino/Auto-GPT" 23 | "Bug Tracker" = "https://github.com/Torantulino/Auto-GPT" 24 | 25 | [tool.black] 26 | line-length = 88 27 | target-version = ['py38'] 28 | include = '\.pyi?$' 29 | extend-exclude = "" 30 | 31 | [tool.isort] 32 | profile = "black" 33 | 34 | [tool.pylint.messages_control] 35 | disable = "C0330, C0326" 36 | 37 | [tool.pylint.format] 38 | max-line-length = "88" -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/sourcery-ai/sourcery 3 | rev: v1.1.0 # Get the latest tag from https://github.com/sourcery-ai/sourcery/tags 4 | hooks: 5 | - id: sourcery 6 | 7 | - repo: https://github.com/pre-commit/pre-commit-hooks 8 | rev: v0.9.2 9 | hooks: 10 | - id: check-added-large-files 11 | args: [ '--maxkb=500' ] 12 | - id: check-byte-order-marker 13 | - id: check-case-conflict 14 | - id: check-merge-conflict 15 | - id: check-symlinks 16 | - id: debug-statements 17 | 18 | - repo: local 19 | hooks: 20 | - id: isort 21 | name: isort-local 22 | entry: isort 23 | language: python 24 | types: [ python ] 25 | exclude: .+/(dist|.venv|venv|build)/.+ 26 | pass_filenames: true 27 | - id: black 28 | name: black-local 29 | entry: black 30 | language: python 31 | types: [ python ] 32 | exclude: .+/(dist|.venv|venv|build)/.+ 33 | pass_filenames: true -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [coverage:run] 2 | branch = True 3 | plugins = 4 | omit = 5 | # omit anything in a .local directory anywhere 6 | */.local/* 7 | 8 | [run] 9 | branch = True 10 | plugins = 11 | omit = 12 | # omit anything in a .local directory anywhere 13 | */.local/* 14 | 15 | [paths] 16 | source = . 17 | 18 | 19 | [report] 20 | # Regexes for lines to exclude from consideration 21 | 22 | omit = 23 | # omit anything in a .local directory anywhere 24 | */.local/* 25 | 26 | exclude_lines = 27 | # Have to re-enable the standard pragma 28 | pragma: no cover 29 | # Don't complain about missing debug-only code: 30 | def __repr__ 31 | if self\.debug 32 | 33 | # Don't complain if tests don't hit defensive assertion code: 34 | raise AssertionError 35 | raise NotImplementedError 36 | 37 | # Don't complain if non-runnable code isn't run: 38 | if 0: 39 | if __name__ == .__main__.: 40 | 41 | # Don't complain about abstract methods, they aren't run: 42 | @(abc\.)?abstractmethod 43 | 44 | ignore_errors = True 45 | -------------------------------------------------------------------------------- /helpers.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | if "%1" == "clean" ( 4 | echo Removing build artifacts and temporary files... 5 | call :clean 6 | ) else if "%1" == "qa" ( 7 | echo Running static analysis tools... 8 | call :qa 9 | ) else if "%1" == "style" ( 10 | echo Running code formatters... 11 | call :style 12 | ) else ( 13 | echo Usage: %0 [clean^|qa^|style] 14 | exit /b 1 15 | ) 16 | 17 | exit /b 0 18 | 19 | :clean 20 | rem Remove build artifacts and temporary files 21 | @del /s /q build 2>nul 22 | @del /s /q dist 2>nul 23 | @del /s /q __pycache__ 2>nul 24 | @del /s /q *.egg-info 2>nul 25 | @del /s /q **\*.egg-info 2>nul 26 | @del /s /q *.pyc 2>nul 27 | @del /s /q **\*.pyc 2>nul 28 | @del /s /q reports 2>nul 29 | echo Done! 30 | exit /b 0 31 | 32 | :qa 33 | rem Run static analysis tools 34 | @flake8 . 35 | @python run_pylint.py 36 | echo Done! 37 | exit /b 0 38 | 39 | :style 40 | rem Format code 41 | @isort . 42 | @black --exclude=".*\/*(dist|venv|.venv|test-results)\/*.*" . 43 | echo Done! 44 | exit /b 0 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Toran Bruce Richards 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Auto-GPT-Todoist 2 | 3 | 4 | Auto-GPT-Todoist plugin transforms your task management experience, helping you stay organized, focused, and productive like never before. 5 | 6 | 7 | 8 | 9 | ![Alt Text](https://i.imgur.com/bYlbXjx.png) 10 | ### Plugin Installation Steps 11 | 12 | for Linux, depending on distro 13 | ``` 14 | sudo apt-get install zip 15 | apk add zip 16 | sudo pacman -S zip 17 | sudo yum install zip 18 | ``` 19 | Mac / Linux / WSL 20 | ``` 21 | cd plugins && git clone https://github.com/danikhan632/Auto-GPT-Todoist-Plugin.git && zip -r ./Auto-GPT-Todoist-Plugin.zip ./Auto-GPT-Todoist-Plugin && rm -rf ./Auto-GPT-Todoist-Plugin && cd .. && ./run.sh --install-plugin-deps 22 | 23 | ``` 24 | Windows, Powershell 25 | ``` 26 | cd plugins; git clone https://github.com/danikhan632/Auto-GPT-Todoist-Plugin.git; Compress-Archive -Path .\Auto-GPT-Todoist-Plugin -DestinationPath .\Auto-GPT-Todoist-Plugin.zip; Remove-Item -Recurse -Force .\Auto-GPT-Todoist-Plugin; cd .. 27 | ``` 28 | 29 | 30 | 31 | 5. **Allowlist the plugin (optional):** 32 | Add the plugin's class name to the `ALLOWLISTED_PLUGINS` in the `.env` file to avoid being prompted with a warning when loading the plugin: 33 | 34 | ``` shell 35 | ALLOWLISTED_PLUGINS=AutoGPT-Todoist-Plugin 36 | TODOIST_TOKEN=Your_api_token 37 | ``` 38 | 39 | If the plugin is not allowlisted, you will be warned before it's loaded. 40 | -------------------------------------------------------------------------------- /.sourcery.yaml: -------------------------------------------------------------------------------- 1 | # 🪄 This is your project's Sourcery configuration file. 2 | 3 | # You can use it to get Sourcery working in the way you want, such as 4 | # ignoring specific refactorings, skipping directories in your project, 5 | # or writing custom rules. 6 | 7 | # 📚 For a complete reference to this file, see the documentation at 8 | # https://docs.sourcery.ai/Configuration/Project-Settings/ 9 | 10 | # This file was auto-generated by Sourcery on 2023-02-25 at 21:07. 11 | 12 | version: '1' # The schema version of this config file 13 | 14 | ignore: # A list of paths or files which Sourcery will ignore. 15 | - .git 16 | - venv 17 | - .venv 18 | - build 19 | - dist 20 | - env 21 | - .env 22 | - .tox 23 | 24 | rule_settings: 25 | enable: 26 | - default 27 | - gpsg 28 | disable: [] # A list of rule IDs Sourcery will never suggest. 29 | rule_types: 30 | - refactoring 31 | - suggestion 32 | - comment 33 | python_version: '3.9' # A string specifying the lowest Python version your project supports. Sourcery will not suggest refactorings requiring a higher Python version. 34 | 35 | # rules: # A list of custom rules Sourcery will include in its analysis. 36 | # - id: no-print-statements 37 | # description: Do not use print statements in the test directory. 38 | # pattern: print(...) 39 | # language: python 40 | # replacement: 41 | # condition: 42 | # explanation: 43 | # paths: 44 | # include: 45 | # - test 46 | # exclude: 47 | # - conftest.py 48 | # tests: [] 49 | # tags: [] 50 | 51 | # rule_tags: {} # Additional rule tags. 52 | 53 | # metrics: 54 | # quality_threshold: 25.0 55 | 56 | # github: 57 | # labels: [] 58 | # ignore_labels: 59 | # - sourcery-ignore 60 | # request_review: author 61 | # sourcery_branch: sourcery/{base_branch} 62 | 63 | # clone_detection: 64 | # min_lines: 3 65 | # min_duplicates: 2 66 | # identical_clones_only: false 67 | 68 | # proxy: 69 | # url: 70 | # ssl_certs_file: 71 | # no_ssl_verify: false 72 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /src/auto_gpt_todoist_plugin/client.py: -------------------------------------------------------------------------------- 1 | import os 2 | from todoist_api_python.api import TodoistAPI 3 | from datetime import datetime 4 | def proj_to_dict(proj): return { 'id': proj.id, 'name': proj.name, 'is_favorite': proj.is_favorite, 'is_inbox_project': proj.is_inbox_project, 'is_shared': proj.is_shared, } 5 | def qtask_to_dict(quickadd_result): return { 'task': task_to_dict(quickadd_result.task), 'resolved_project_name': quickadd_result.resolved_project_name} 6 | def task_to_dict(task): return { 'id': task.id, 'content': task.content, 'created_at': task.created_at, 'priority': task.priority, 'project_id': task.project_id, 'section_id': task.section_id } 7 | def section_to_dict(sect): return { "id": sect.id, "name": sect.name, "project_id": sect.project_id, } 8 | def label_to_dict(label): return { "id": label.id, "name": label.name, "color": label.color, } 9 | class Client: 10 | def __init__(self): 11 | self.api = TodoistAPI(os.environ.get('TODOIST_TOKEN')) if os.environ.get('TODOIST_TOKEN') else print("The TODOIST_TOKEN environment variable is missing.") 12 | 13 | def get_projects(self): 14 | projects =self.api.get_projects() 15 | project_dicts = [proj_to_dict(project) for project in projects] 16 | return project_dicts 17 | 18 | def get_project(self, project_id): 19 | return proj_to_dict(self.api.get_project(project_id)) 20 | 21 | 22 | def get_collaborators(self, project_id): 23 | return self.api.get_collaborators(project_id) 24 | def get_comments(self, project_id=None, task_id=None): 25 | if project_id: 26 | return self.api.get_comments(project_id=project_id) 27 | elif task_id: 28 | return self.api.get_comments(task_id=task_id) 29 | else: 30 | print("Either a project_id or a task_id must be provided.") 31 | 32 | 33 | def get_label(self, label_id): 34 | labels = self.get_labels() 35 | label_ids = [label['id'] for label in labels] 36 | if label_id in label_ids: 37 | return self.api.get_label(label_id) 38 | else: 39 | print(f"Label with id {label_id} does not exist.") 40 | return None 41 | 42 | def get_labels(self): 43 | labels =self.api.get_labels() 44 | return [label_to_dict(label) for label in labels] 45 | 46 | 47 | def get_section(self, section_id): 48 | sections = self.get_sections() 49 | section_ids = [section['id'] for section in sections] 50 | if section_id in section_ids: 51 | return self.api.get_section(section_id) 52 | else: 53 | print(f"Label with id {section_id} does not exist.") 54 | return None 55 | 56 | def get_sections(self): 57 | sections =self.api.get_sections() 58 | return [section_to_dict(section) for section in sections] 59 | def get_shared_labels(self): 60 | return self.api.get_shared_labels() 61 | 62 | def get_task(self, task_id): 63 | tasks = self.get_tasks() 64 | task_ids = [task['id'] for task in tasks] 65 | if task_id in task_ids: 66 | return self.api.get_task(task_id) 67 | else: 68 | print(f"Task with id {task_id} does not exist.") 69 | return None 70 | 71 | def get_tasks(self): 72 | tasks =self.api.get_tasks() 73 | return [task_to_dict(task) for task in tasks] 74 | 75 | 76 | def add_comment(self, content, project_id=None, task_id=None): 77 | if project_id: 78 | return self.api.add_comment(content=content, project_id=project_id) 79 | elif task_id: 80 | return self.api.add_comment(content=content, task_id=task_id) 81 | else: 82 | print("Either a project_id or a task_id must be provided.") 83 | return None 84 | 85 | def get_todays_tasks(self): 86 | tasks = self.get_tasks() 87 | today = date.today().isoformat() 88 | todays_tasks = [task for task in tasks if task['due'] is not None and task['due']['date'] == today] 89 | return todays_tasks 90 | 91 | def add_label(self, name): 92 | return label_to_dict(self.api.add_label(name=name)) 93 | 94 | 95 | def add_project(self, name): 96 | return proj_to_dict(self.api.add_project(name=name)) 97 | 98 | def add_section(self, name, project_id): 99 | return section_to_dict(self.api.add_section(name=name, project_id=project_id)) 100 | 101 | def add_task(self, content, project_id=None, due=None): 102 | kwargs = {'content': content} 103 | if project_id: 104 | kwargs['project_id'] = project_id 105 | if due: 106 | kwargs['due'] = {'string': due} 107 | return task_to_dict(self.api.add_task(**kwargs)) 108 | 109 | def quick_add_task(self, text): 110 | return qtask_to_dict(self.api.quick_add_task(text)) 111 | # New methods 112 | def remove_shared_label(self, name: str) -> bool: 113 | labels = self.get_labels() 114 | label_names = [label['name'] for label in labels] 115 | if name in label_names: 116 | return self.api.remove_shared_label(name) 117 | else: 118 | print(f"Shared label '{name}' does not exist.") 119 | return False 120 | 121 | def rename_shared_label(self, name: str, new_name: str) -> bool: 122 | labels = self.get_labels() 123 | label_names = [label['name'] for label in labels] 124 | if name in label_names: 125 | return self.api.rename_shared_label(name, new_name) 126 | else: 127 | print(f"Shared label '{name}' does not exist.") 128 | return False 129 | 130 | def reopen_task(self, task_id: str) -> bool: 131 | if self.get_task(task_id): 132 | return self.api.reopen_task(task_id) 133 | else: 134 | print(f"Task with id {task_id} does not exist.") 135 | return False 136 | 137 | def update_comment(self, comment_id: str, content: str) -> bool: 138 | comments = self.get_comments() 139 | comment_ids = [comment['id'] for comment in comments] 140 | if comment_id in comment_ids: 141 | return self.api.update_comment(comment_id, content) 142 | else: 143 | print(f"Comment with id {comment_id} does not exist.") 144 | return False 145 | 146 | def update_label(self, label_id: str) -> bool: 147 | if self.get_label(label_id): 148 | return self.api.update_label(label_id) 149 | else: 150 | print(f"Label with id {label_id} does not exist.") 151 | return False 152 | 153 | def update_project(self, project_id: str) -> bool: 154 | if self.get_project(project_id): 155 | return self.api.update_project(project_id) 156 | else: 157 | print(f"Project with id {project_id} does not exist.") 158 | return False 159 | 160 | def update_section(self, section_id: str, name: str) -> bool: 161 | if self.get_section(section_id): 162 | return self.api.update_section(section_id, name) 163 | else: 164 | print(f"Section with id {section_id} does not exist.") 165 | return False 166 | 167 | def update_task(self, task_id: str) -> bool: 168 | if self.get_task(task_id): 169 | return self.api.update_task(task_id) 170 | else: 171 | print(f"Task with id {task_id} does not exist.") 172 | return False 173 | 174 | def close_task(self, task_id: str) -> bool: 175 | if self.get_task(task_id): 176 | return self.api.close_task(task_id) 177 | else: 178 | print(f"Task with id {task_id} does not exist.") 179 | return False 180 | 181 | def delete_comment(self, comment_id: str) -> bool: 182 | comments = self.get_comments() 183 | comment_ids = [comment['id'] for comment in comments] 184 | if comment_id in comment_ids: 185 | return self.api.delete_comment(comment_id) 186 | else: 187 | print(f"Comment with id {comment_id} does not exist.") 188 | return False 189 | 190 | def delete_label(self, label_id: str) -> bool: 191 | if self.get_label(label_id): 192 | return self.api.delete_label(label_id) 193 | else: 194 | print(f"Label with id {label_id} does not exist.") 195 | return False 196 | 197 | def delete_project(self, project_id: str) -> bool: 198 | if self.get_project(project_id): 199 | return self.api.delete_project(project_id) 200 | else: 201 | print(f"Project with id {project_id} does not exist.") 202 | return False 203 | 204 | def delete_section(self, section_id: str) -> bool: 205 | if self.get_section(section_id): 206 | return self.api.delete_section(section_id) 207 | else: 208 | print(f"Section with id {section_id} does not exist.") 209 | return False 210 | 211 | def delete_task(self, task_id: str) -> bool: 212 | if self.get_task(task_id): 213 | return self.api.delete_task(task_id) 214 | else: 215 | print(f"Task with id {task_id} does not exist.") 216 | return False 217 | -------------------------------------------------------------------------------- /src/auto_gpt_todoist_plugin/__init__.py: -------------------------------------------------------------------------------- 1 | """This is a plugin to use Auto-GPT with Todoist""" 2 | from typing import Any, Dict, List, Optional, Tuple, TypeVar, TypedDict 3 | from auto_gpt_plugin_template import AutoGPTPluginTemplate 4 | 5 | 6 | from .client import Client 7 | 8 | PromptGenerator = TypeVar("PromptGenerator") 9 | 10 | class Message(TypedDict): 11 | role: str 12 | content: str 13 | 14 | 15 | class AutoGPTTodoistPlugin(AutoGPTPluginTemplate): 16 | """ 17 | This is a plugin to use Auto-GPT with Todoist. 18 | """ 19 | 20 | def __init__(self): 21 | super().__init__() 22 | self._name = "Auto-GPT-Todoist" 23 | self._version = "0.1.0" 24 | self._description = "This is a plugin for AutoGPT to create, view, modify and interface with todoist" 25 | self.cli= Client() 26 | 27 | 28 | def post_prompt(self, prompt: PromptGenerator) -> PromptGenerator: 29 | prompt.add_command( 30 | "Get all projects", 31 | "get projects", 32 | {}, 33 | self.cli.get_projects 34 | ), 35 | prompt.add_command( 36 | "Get a specific project", 37 | "get project", 38 | {"project_id": ""}, 39 | self.cli.get_project 40 | ), 41 | prompt.add_command( 42 | "Get collaborators of a project", 43 | "get collaborators", 44 | {"project_id": ""}, 45 | self.cli.get_collaborators 46 | ), 47 | prompt.add_command( 48 | "Get comments", 49 | "get comments", 50 | { 51 | "project_id": "", 52 | "task_id": "", 53 | }, 54 | self.cli.get_comments 55 | ), 56 | prompt.add_command( 57 | "Get label by ID", 58 | "get label", 59 | {"label_id": ""}, 60 | self.cli.get_label 61 | ), 62 | # ... 63 | prompt.add_command( 64 | "Get labels", 65 | "get labels", 66 | {}, 67 | self.cli.get_labels 68 | ), 69 | prompt.add_command( 70 | "Get section by ID", 71 | "get section", 72 | {"section_id": ""}, 73 | self.cli.get_section 74 | ), 75 | prompt.add_command( 76 | "Get sections", 77 | "get sections", 78 | {}, 79 | self.cli.get_sections 80 | ), 81 | prompt.add_command( 82 | "Get shared labels", 83 | "get shared labels", 84 | {}, 85 | self.cli.get_shared_labels 86 | ), 87 | prompt.add_command( 88 | "Get task by ID", 89 | "get task", 90 | {"task_id": ""}, 91 | self.cli.get_task 92 | ), 93 | prompt.add_command( 94 | "Get tasks", 95 | "get tasks", 96 | {}, 97 | self.cli.get_tasks 98 | ), 99 | prompt.add_command( 100 | "Add comment", 101 | "add comment", 102 | { 103 | "content": "", 104 | "project_id": "", 105 | "task_id": "", 106 | }, 107 | self.cli.add_comment 108 | ), 109 | prompt.add_command( 110 | "Get today's tasks", 111 | "get today's tasks", 112 | {}, 113 | self.cli.get_todays_tasks 114 | ), 115 | prompt.add_command( 116 | "Add label", 117 | "add label", 118 | {"name": ""}, 119 | self.cli.add_label 120 | ), 121 | prompt.add_command( 122 | "Add project", 123 | "add project", 124 | {"name": ""}, 125 | self.cli.add_project 126 | ), 127 | prompt.add_command( 128 | "Add section", 129 | "add section", 130 | { 131 | "name": "", 132 | "project_id": "", 133 | }, 134 | self.cli.add_section 135 | ), 136 | prompt.add_command( 137 | "Add task", 138 | "add task", 139 | { 140 | "content": "", 141 | "project_id": "", 142 | "due": "", 143 | }, 144 | self.cli.add_task 145 | ), 146 | prompt.add_command( 147 | "Quick add task", 148 | "quick add task", 149 | {"text": ""}, 150 | self.cli.quick_add_task 151 | ), 152 | prompt.add_command( 153 | "Remove shared label", 154 | "remove shared label", 155 | {"name": ""}, 156 | self.cli.remove_shared_label 157 | ), 158 | prompt.add_command( 159 | "Rename shared label", 160 | "rename shared label", 161 | { 162 | "name": "", 163 | "new_name": "", 164 | }, 165 | self.cli.rename_shared_label 166 | ), 167 | prompt.add_command( 168 | "Reopen task", 169 | "reopen task", 170 | {"task_id": ""}, 171 | self.cli.reopen_task 172 | ), 173 | prompt.add_command( 174 | "Update comment", 175 | "update comment", 176 | { 177 | "comment_id": "", 178 | "content": "", 179 | }, 180 | self.cli.update_comment 181 | ), 182 | prompt.add_command( 183 | "Update label", 184 | "update label", 185 | {"label_id": ""}, 186 | self.cli.update_label 187 | ), 188 | prompt.add_command( 189 | "Update project", 190 | "update project", 191 | {"project_id": ""}, 192 | self.cli.update_project 193 | ), 194 | prompt.add_command( 195 | "Update section", 196 | "update section", 197 | { 198 | "section_id": "", 199 | "name": "", 200 | }, 201 | self.cli.update_section 202 | ), 203 | prompt.add_command( 204 | "Update task", 205 | "update task", 206 | {"task_id": ""}, 207 | self.cli.update_task 208 | ), 209 | prompt.add_command( 210 | "Close task", 211 | "close task", 212 | {"task_id": ""}, 213 | self.cli.close_task 214 | ), 215 | prompt.add_command( 216 | "Delete comment", 217 | "delete comment", 218 | {"comment_id": ""}, 219 | self.cli.delete_comment 220 | ), 221 | prompt.add_command( 222 | "Delete label", 223 | "delete label", 224 | {"label_id": ""}, 225 | self.cli.delete_label 226 | ), 227 | prompt.add_command( 228 | "Delete project", 229 | "delete project", 230 | {"project_id": ""}, 231 | self.cli.delete_project 232 | ), 233 | prompt.add_command( 234 | "Delete section", 235 | "delete section", 236 | {"section_id": ""}, 237 | self.cli.delete_section 238 | ), 239 | prompt.add_command( 240 | "Delete task", 241 | "delete task", 242 | {"task_id": ""}, 243 | self.cli.delete_task 244 | ) 245 | return prompt 246 | # ______________________________________________________________________________________________________________________ 247 | 248 | # ______________________________________________________________________________________________________________________ 249 | def handle_chat_completion( 250 | self, messages: List[Message], model: str, temperature: float, max_tokens: int 251 | ) -> str: 252 | """This method is called when the chat completion is done. 253 | Args: 254 | messages (List[Message]): The messages. 255 | model (str): The model name. 256 | temperature (float): The temperature. 257 | max_tokens (int): The max tokens. 258 | Returns: 259 | str: The resulting response. 260 | """ 261 | pass 262 | 263 | def can_handle_post_prompt(self) -> bool: 264 | """This method is called to check that the plugin can 265 | handle the post_prompt method. 266 | Returns: 267 | bool: True if the plugin can handle the post_prompt method.""" 268 | return True 269 | 270 | def can_handle_on_response(self) -> bool: 271 | """This method is called to check that the plugin can 272 | handle the on_response method. 273 | Returns: 274 | bool: True if the plugin can handle the on_response method.""" 275 | return False 276 | 277 | def on_response(self, response: str, *args, **kwargs) -> str: 278 | """This method is called when a response is received from the model.""" 279 | pass 280 | 281 | def can_handle_on_planning(self) -> bool: 282 | """This method is called to check that the plugin can 283 | handle the on_planning method. 284 | Returns: 285 | bool: True if the plugin can handle the on_planning method.""" 286 | return False 287 | 288 | def on_planning( 289 | self, prompt: PromptGenerator, messages: List[Message] 290 | ) -> Optional[str]: 291 | """This method is called before the planning chat completion is done. 292 | Args: 293 | prompt (PromptGenerator): The prompt generator. 294 | messages (List[str]): The list of messages. 295 | """ 296 | pass 297 | 298 | def can_handle_post_planning(self) -> bool: 299 | """This method is called to check that the plugin can 300 | handle the post_planning method. 301 | Returns: 302 | bool: True if the plugin can handle the post_planning method.""" 303 | return False 304 | 305 | def post_planning(self, response: str) -> str: 306 | """This method is called after the planning chat completion is done. 307 | Args: 308 | response (str): The response. 309 | Returns: 310 | str: The resulting response. 311 | """ 312 | pass 313 | 314 | def can_handle_pre_instruction(self) -> bool: 315 | """This method is called to check that the plugin can 316 | handle the pre_instruction method. 317 | Returns: 318 | bool: True if the plugin can handle the pre_instruction method.""" 319 | return False 320 | 321 | def pre_instruction(self, messages: List[Message]) -> List[Message]: 322 | """This method is called before the instruction chat is done. 323 | Args: 324 | messages (List[Message]): The list of context messages. 325 | Returns: 326 | List[Message]: The resulting list of messages. 327 | """ 328 | pass 329 | 330 | def can_handle_on_instruction(self) -> bool: 331 | """This method is called to check that the plugin can 332 | handle the on_instruction method. 333 | Returns: 334 | bool: True if the plugin can handle the on_instruction method.""" 335 | return False 336 | 337 | def on_instruction(self, messages: List[Message]) -> Optional[str]: 338 | """This method is called when the instruction chat is done. 339 | Args: 340 | messages (List[Message]): The list of context messages. 341 | Returns: 342 | Optional[str]: The resulting message. 343 | """ 344 | pass 345 | 346 | def can_handle_post_instruction(self) -> bool: 347 | """This method is called to check that the plugin can 348 | handle the post_instruction method. 349 | Returns: 350 | bool: True if the plugin can handle the post_instruction method.""" 351 | return False 352 | 353 | def post_instruction(self, response: str) -> str: 354 | """This method is called after the instruction chat is done. 355 | Args: 356 | response (str): The response. 357 | Returns: 358 | str: The resulting response. 359 | """ 360 | pass 361 | 362 | def can_handle_pre_command(self) -> bool: 363 | """This method is called to check that the plugin can 364 | handle the pre_command method. 365 | Returns: 366 | bool: True if the plugin can handle the pre_command method.""" 367 | return False 368 | 369 | def pre_command( 370 | self, command_name: str, arguments: Dict[str, Any] 371 | ) -> Tuple[str, Dict[str, Any]]: 372 | """This method is called before the command is executed. 373 | Args: 374 | command_name (str): The command name. 375 | arguments (Dict[str, Any]): The arguments. 376 | Returns: 377 | Tuple[str, Dict[str, Any]]: The command name and the arguments. 378 | """ 379 | pass 380 | 381 | def can_handle_post_command(self) -> bool: 382 | """This method is called to check that the plugin can 383 | handle the post_command method. 384 | Returns: 385 | bool: True if the plugin can handle the post_command method.""" 386 | return False 387 | 388 | def post_command(self, command_name: str, response: str) -> str: 389 | """This method is called after the command is executed. 390 | Args: 391 | command_name (str): The command name. 392 | response (str): The response. 393 | Returns: 394 | str: The resulting response. 395 | """ 396 | pass 397 | 398 | def can_handle_chat_completion( 399 | self, messages: Dict[Any, Any], model: str, temperature: float, max_tokens: int 400 | ) -> bool: 401 | """This method is called to check that the plugin can 402 | handle the chat_completion method. 403 | Args: 404 | messages (List[Message]): The messages. 405 | model (str): The model name. 406 | temperature (float): The temperature. 407 | max_tokens (int): The max tokens. 408 | Returns: 409 | bool: True if the plugin can handle the chat_completion method.""" 410 | return False 411 | 412 | 413 | 414 | 415 | 416 | # prompt.add_command( 417 | # "Add two numbers", 418 | # "add 2 numbers", 419 | # { 420 | # "num": "", 421 | # "num2": "", 422 | # }, 423 | # self.cli.add_numbers 424 | # ), 425 | # prompt.add_command( 426 | # "Subtract two numbers", 427 | # "subtract 2 numbers", 428 | # { 429 | # "num": "", 430 | # "num2": "", 431 | # }, 432 | # self.cli.sum_numbers 433 | # ), 434 | 435 | # Class Client: 436 | # ...other code 437 | 438 | # def add_numbers(self, num, num2): 439 | # return num+num2 440 | # def sub_numbers(self, num, num2): 441 | # return num-num2 442 | # LOOK AT THE EXAMPLE ABOVE AND CREATE add_command ENTRIES BASED IN THE CODE BELOW. THIS IS FOR -------------------------------------------------------------------------------- /pylintrc: -------------------------------------------------------------------------------- 1 | # This Pylint rcfile contains a best-effort configuration to uphold the 2 | # best-practices and style described in the Google Python style guide: 3 | # https://google.github.io/styleguide/pyguide.html 4 | # 5 | # Its canonical open-source location is: 6 | # https://google.github.io/styleguide/pylintrc 7 | 8 | [MASTER] 9 | 10 | # Files or directories to be skipped. They should be base names, not paths. 11 | ignore= 12 | 13 | # Files or directories matching the regex patterns are skipped. The regex 14 | # matches against base names, not paths. 15 | ignore-patterns= 16 | 17 | # Pickle collected data for later comparisons. 18 | persistent=no 19 | 20 | # List of plugins (as comma separated values of python modules names) to load, 21 | # usually to register additional checkers. 22 | load-plugins= 23 | 24 | # Use multiple processes to speed up Pylint. 25 | jobs=4 26 | 27 | # Allow loading of arbitrary C extensions. Extensions are imported into the 28 | # active Python interpreter and may run arbitrary code. 29 | unsafe-load-any-extension=no 30 | 31 | 32 | [MESSAGES CONTROL] 33 | 34 | ignore=*.pyc 35 | # Only show warnings with the listed confidence levels. Leave empty to show 36 | # all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED 37 | confidence= 38 | 39 | # Enable the message, report, category or checker with the given id(s). You can 40 | # either give multiple identifier separated by comma (,) or put this option 41 | # multiple time (only on the command line, not in the configuration file where 42 | # it should appear only once). See also the "--disable" option for examples. 43 | #enable= 44 | 45 | # Disable the message, report, category or checker with the given id(s). You 46 | # can either give multiple identifiers separated by comma (,) or put this 47 | # option multiple times (only on the command line, not in the configuration 48 | # file where it should appear only once).You can also use "--disable=all" to 49 | # disable everything first and then reenable specific checks. For example, if 50 | # you want to run only the similarities checker, you can use "--disable=all 51 | # --enable=similarities". If you want to run only the classes checker, but have 52 | # no Warning level messages displayed, use"--disable=all --enable=classes 53 | # --disable=W" 54 | disable=abstract-method, 55 | parse-error, 56 | apply-builtin, 57 | arguments-differ, 58 | attribute-defined-outside-init, 59 | backtick, 60 | bad-option-value, 61 | basestring-builtin, 62 | buffer-builtin, 63 | c-extension-no-member, 64 | consider-using-enumerate, 65 | cmp-builtin, 66 | cmp-method, 67 | coerce-builtin, 68 | coerce-method, 69 | delslice-method, 70 | div-method, 71 | duplicate-code, 72 | eq-without-hash, 73 | execfile-builtin, 74 | file-builtin, 75 | filter-builtin-not-iterating, 76 | fixme, 77 | getslice-method, 78 | global-statement, 79 | hex-method, 80 | idiv-method, 81 | implicit-str-concat, 82 | import-error, 83 | import-self, 84 | import-star-module-level, 85 | inconsistent-return-statements, 86 | input-builtin, 87 | intern-builtin, 88 | invalid-str-codec, 89 | locally-disabled, 90 | long-builtin, 91 | long-suffix, 92 | map-builtin-not-iterating, 93 | misplaced-comparison-constant, 94 | missing-function-docstring, 95 | metaclass-assignment, 96 | next-method-called, 97 | next-method-defined, 98 | no-absolute-import, 99 | no-else-break, 100 | no-else-continue, 101 | no-else-raise, 102 | no-else-return, 103 | no-init, # added 104 | no-member, 105 | no-name-in-module, 106 | no-self-use, 107 | nonzero-method, 108 | oct-method, 109 | old-division, 110 | old-ne-operator, 111 | old-octal-literal, 112 | old-raise-syntax, 113 | parameter-unpacking, 114 | print-statement, 115 | raising-string, 116 | range-builtin-not-iterating, 117 | raw_input-builtin, 118 | rdiv-method, 119 | reduce-builtin, 120 | relative-import, 121 | reload-builtin, 122 | round-builtin, 123 | setslice-method, 124 | signature-differs, 125 | standarderror-builtin, 126 | suppressed-message, 127 | sys-max-int, 128 | too-few-public-methods, 129 | too-many-ancestors, 130 | too-many-arguments, 131 | too-many-boolean-expressions, 132 | too-many-branches, 133 | too-many-instance-attributes, 134 | too-many-locals, 135 | too-many-nested-blocks, 136 | too-many-public-methods, 137 | too-many-return-statements, 138 | too-many-statements, 139 | trailing-newlines, 140 | unichr-builtin, 141 | unicode-builtin, 142 | unnecessary-pass, 143 | unpacking-in-except, 144 | useless-else-on-loop, 145 | useless-object-inheritance, 146 | useless-suppression, 147 | using-cmp-argument, 148 | wrong-import-order, 149 | xrange-builtin, 150 | zip-builtin-not-iterating, 151 | 152 | 153 | [REPORTS] 154 | 155 | # Set the output format. Available formats are text, parseable, colorized, msvs 156 | # (visual studio) and html. You can also give a reporter class, eg 157 | # mypackage.mymodule.MyReporterClass. 158 | output-format=text 159 | 160 | # Tells whether to display a full report or only the messages 161 | reports=no 162 | 163 | # Python expression which should return a note less than 10 (10 is the highest 164 | # note). You have access to the variables errors warning, statement which 165 | # respectively contain the number of errors / warnings messages and the total 166 | # number of statements analyzed. This is used by the global evaluation report 167 | # (RP0004). 168 | evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) 169 | 170 | # Template used to display messages. This is a python new-style format string 171 | # used to format the message information. See doc for all details 172 | #msg-template= 173 | 174 | 175 | [BASIC] 176 | 177 | # Good variable names which should always be accepted, separated by a comma 178 | good-names=main,_ 179 | 180 | # Bad variable names which should always be refused, separated by a comma 181 | bad-names= 182 | 183 | # Colon-delimited sets of names that determine each other's naming style when 184 | # the name regexes allow several styles. 185 | name-group= 186 | 187 | # Include a hint for the correct naming format with invalid-name 188 | include-naming-hint=no 189 | 190 | # List of decorators that produce properties, such as abc.abstractproperty. Add 191 | # to this list to register other decorators that produce valid properties. 192 | property-classes=abc.abstractproperty,cached_property.cached_property,cached_property.threaded_cached_property,cached_property.cached_property_with_ttl,cached_property.threaded_cached_property_with_ttl 193 | 194 | # Regular expression matching correct function names 195 | function-rgx=^(?:(?PsetUp|tearDown|setUpModule|tearDownModule)|(?P_?[A-Z][a-zA-Z0-9]*)|(?P_?[a-z][a-z0-9_]*))$ 196 | 197 | # Regular expression matching correct variable names 198 | variable-rgx=^[a-z][a-z0-9_]*$ 199 | 200 | # Regular expression matching correct constant names 201 | const-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$ 202 | 203 | # Regular expression matching correct attribute names 204 | attr-rgx=^_{0,2}[a-z][a-z0-9_]*$ 205 | 206 | # Regular expression matching correct argument names 207 | argument-rgx=^[a-z][a-z0-9_]*$ 208 | 209 | # Regular expression matching correct class attribute names 210 | class-attribute-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$ 211 | 212 | # Regular expression matching correct inline iteration names 213 | inlinevar-rgx=^[a-z][a-z0-9_]*$ 214 | 215 | # Regular expression matching correct class names 216 | class-rgx=^_?[A-Z][a-zA-Z0-9]*$ 217 | 218 | # Regular expression matching correct module names 219 | module-rgx=^(_?[a-z][a-z0-9_]*|__init__|__main__)$ 220 | 221 | # Regular expression matching correct method names 222 | method-rgx=(?x)^(?:(?P_[a-z0-9_]+__|runTest|setUp|tearDown|setUpTestCase|tearDownTestCase|setupSelf|tearDownClass|setUpClass|(test|assert)_*[A-Z0-9][a-zA-Z0-9_]*|next)|(?P_{0,2}[A-Z][a-zA-Z0-9_]*)|(?P_{0,2}[a-z][a-z0-9_]*))$ 223 | 224 | # Regular expression which should only match function or class names that do 225 | # not require a docstring. 226 | no-docstring-rgx=(__.*__|main|test.*|.*test|.*Test)$ 227 | 228 | # Minimum line length for functions/classes that require docstrings, shorter 229 | # ones are exempt. 230 | docstring-min-length=10 231 | 232 | 233 | [TYPECHECK] 234 | 235 | # List of decorators that produce context managers, such as 236 | # contextlib.contextmanager. Add to this list to register other decorators that 237 | # produce valid context managers. 238 | contextmanager-decorators=contextlib.contextmanager,contextlib2.contextmanager 239 | 240 | # Tells whether missing members accessed in mixin class should be ignored. A 241 | # mixin class is detected if its name ends with "mixin" (case insensitive). 242 | ignore-mixin-members=yes 243 | 244 | # List of module names for which member attributes should not be checked 245 | # (useful for modules/projects where namespaces are manipulated during runtime 246 | # and thus existing member attributes cannot be deduced by static analysis. It 247 | # supports qualified module names, as well as Unix pattern matching. 248 | ignored-modules= 249 | 250 | # List of class names for which member attributes should not be checked (useful 251 | # for classes with dynamically set attributes). This supports the use of 252 | # qualified names. 253 | ignored-classes=optparse.Values,thread._local,_thread._local 254 | 255 | # List of members which are set dynamically and missed by pylint inference 256 | # system, and so shouldn't trigger E1101 when accessed. Python regular 257 | # expressions are accepted. 258 | generated-members= 259 | 260 | 261 | [FORMAT] 262 | 263 | # Maximum number of characters on a single line. 264 | max-line-length=88 265 | 266 | # TODO(https://github.com/PyCQA/pylint/issues/3352): Direct pylint to exempt 267 | # lines made too long by directives to pytype. 268 | 269 | # Regexp for a line that is allowed to be longer than the limit. 270 | ignore-long-lines=(?x)( 271 | ^\s*(\#\ )??$| 272 | ^\s*(from\s+\S+\s+)?import\s+.+$) 273 | 274 | # Allow the body of an if to be on the same line as the test if there is no 275 | # else. 276 | single-line-if-stmt=yes 277 | 278 | # Maximum number of lines in a module 279 | max-module-lines=99999 280 | 281 | # String used as indentation unit. The internal Google style guide mandates 2 282 | # spaces. Google's externaly-published style guide says 4, consistent with 283 | # PEP 8. Here, we use 2 spaces, for conformity with many open-sourced Google 284 | # projects (like TensorFlow). 285 | indent-string=' ' 286 | 287 | # Number of spaces of indent required inside a hanging or continued line. 288 | indent-after-paren=4 289 | 290 | # Expected format of line ending, e.g. empty (any line ending), LF or CRLF. 291 | expected-line-ending-format= 292 | 293 | 294 | [MISCELLANEOUS] 295 | 296 | # List of note tags to take in consideration, separated by a comma. 297 | notes=TODO 298 | 299 | 300 | [STRING] 301 | 302 | # This flag controls whether inconsistent-quotes generates a warning when the 303 | # character used as a quote delimiter is used inconsistently within a module. 304 | check-quote-consistency=yes 305 | 306 | 307 | [VARIABLES] 308 | 309 | # Tells whether we should check for unused import in __init__ files. 310 | init-import=no 311 | 312 | # A regular expression matching the name of dummy variables (i.e. expectedly 313 | # not used). 314 | dummy-variables-rgx=^\*{0,2}(_$|unused_|dummy_) 315 | 316 | # List of additional names supposed to be defined in builtins. Remember that 317 | # you should avoid to define new builtins when possible. 318 | additional-builtins= 319 | 320 | # List of strings which can identify a callback function by name. A callback 321 | # name must start or end with one of those strings. 322 | callbacks=cb_,_cb 323 | 324 | # List of qualified module names which can have objects that can redefine 325 | # builtins. 326 | redefining-builtins-modules=six,six.moves,past.builtins,future.builtins,functools 327 | 328 | 329 | [LOGGING] 330 | 331 | # Logging modules to check that the string format arguments are in logging 332 | # function parameter format 333 | logging-modules=logging,absl.logging,tensorflow.io.logging 334 | 335 | 336 | [SIMILARITIES] 337 | 338 | # Minimum lines number of a similarity. 339 | min-similarity-lines=4 340 | 341 | # Ignore comments when computing similarities. 342 | ignore-comments=yes 343 | 344 | # Ignore docstrings when computing similarities. 345 | ignore-docstrings=yes 346 | 347 | # Ignore imports when computing similarities. 348 | ignore-imports=no 349 | 350 | 351 | [SPELLING] 352 | 353 | # Spelling dictionary name. Available dictionaries: none. To make it working 354 | # install python-enchant package. 355 | spelling-dict= 356 | 357 | # List of comma separated words that should not be checked. 358 | spelling-ignore-words= 359 | 360 | # A path to a file that contains private dictionary; one word per line. 361 | spelling-private-dict-file= 362 | 363 | # Tells whether to store unknown words to indicated private dictionary in 364 | # --spelling-private-dict-file option instead of raising a message. 365 | spelling-store-unknown-words=no 366 | 367 | 368 | [IMPORTS] 369 | 370 | # Deprecated modules which should not be used, separated by a comma 371 | deprecated-modules=regsub, 372 | TERMIOS, 373 | Bastion, 374 | rexec, 375 | sets 376 | 377 | # Create a graph of every (i.e. internal and external) dependencies in the 378 | # given file (report RP0402 must not be disabled) 379 | import-graph= 380 | 381 | # Create a graph of external dependencies in the given file (report RP0402 must 382 | # not be disabled) 383 | ext-import-graph= 384 | 385 | # Create a graph of internal dependencies in the given file (report RP0402 must 386 | # not be disabled) 387 | int-import-graph= 388 | 389 | # Force import order to recognize a module as part of the standard 390 | # compatibility libraries. 391 | known-standard-library= 392 | 393 | # Force import order to recognize a module as part of a third party library. 394 | known-third-party=enchant, absl 395 | 396 | # Analyse import fallback blocks. This can be used to support both Python 2 and 397 | # 3 compatible code, which means that the block might have code that exists 398 | # only in one or another interpreter, leading to false positives when analysed. 399 | analyse-fallback-blocks=no 400 | 401 | 402 | [CLASSES] 403 | 404 | # List of method names used to declare (i.e. assign) instance attributes. 405 | defining-attr-methods=__init__, 406 | __new__, 407 | setUp 408 | 409 | # List of member names, which should be excluded from the protected access 410 | # warning. 411 | exclude-protected=_asdict, 412 | _fields, 413 | _replace, 414 | _source, 415 | _make 416 | 417 | # List of valid names for the first argument in a class method. 418 | valid-classmethod-first-arg=cls, 419 | class_ 420 | 421 | # List of valid names for the first argument in a metaclass class method. 422 | valid-metaclass-classmethod-first-arg=mcs 423 | 424 | 425 | [EXCEPTIONS] 426 | 427 | # Exceptions that will emit a warning when being caught. Defaults to 428 | # "Exception" 429 | overgeneral-exceptions=builtins.StandardError, 430 | builtins.Exception, 431 | builtins.BaseException 432 | --------------------------------------------------------------------------------