├── tests ├── test_script.py ├── __init__.py ├── test_config.py ├── test_utils.py ├── test_connection.py └── test_mongobar.py ├── mongobar ├── __version__.py ├── __init__.py ├── exceptions.py ├── utils.py ├── config.py ├── connection.py ├── mongobar.py ├── scripts │ └── mongobar └── data │ └── verbs.txt ├── assets ├── help.png ├── hosts.png ├── meta.png ├── psd │ ├── help │ ├── hosts │ ├── meta │ ├── backups │ ├── config │ ├── server │ └── help_backup ├── backups.png ├── config.png ├── server.png └── help_backup.png ├── .gitignore ├── .travis.yml ├── TODO.txt ├── .mongobar_config.json ├── init_auth.sh ├── docker-compose.yml ├── LICENSE.txt ├── Dockerfile ├── setup.py ├── CHANGELOG.md └── README.md /tests/test_script.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | # placeholder -------------------------------------------------------------------------------- /mongobar/__version__.py: -------------------------------------------------------------------------------- 1 | __version__ = "0.0.13" 2 | -------------------------------------------------------------------------------- /mongobar/__init__.py: -------------------------------------------------------------------------------- 1 | from mongobar.mongobar import Mongobar 2 | -------------------------------------------------------------------------------- /assets/help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisantonellis/mongobar/HEAD/assets/help.png -------------------------------------------------------------------------------- /assets/hosts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisantonellis/mongobar/HEAD/assets/hosts.png -------------------------------------------------------------------------------- /assets/meta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisantonellis/mongobar/HEAD/assets/meta.png -------------------------------------------------------------------------------- /assets/psd/help: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisantonellis/mongobar/HEAD/assets/psd/help -------------------------------------------------------------------------------- /assets/psd/hosts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisantonellis/mongobar/HEAD/assets/psd/hosts -------------------------------------------------------------------------------- /assets/psd/meta: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisantonellis/mongobar/HEAD/assets/psd/meta -------------------------------------------------------------------------------- /assets/backups.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisantonellis/mongobar/HEAD/assets/backups.png -------------------------------------------------------------------------------- /assets/config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisantonellis/mongobar/HEAD/assets/config.png -------------------------------------------------------------------------------- /assets/psd/backups: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisantonellis/mongobar/HEAD/assets/psd/backups -------------------------------------------------------------------------------- /assets/psd/config: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisantonellis/mongobar/HEAD/assets/psd/config -------------------------------------------------------------------------------- /assets/psd/server: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisantonellis/mongobar/HEAD/assets/psd/server -------------------------------------------------------------------------------- /assets/server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisantonellis/mongobar/HEAD/assets/server.png -------------------------------------------------------------------------------- /assets/help_backup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisantonellis/mongobar/HEAD/assets/help_backup.png -------------------------------------------------------------------------------- /assets/psd/help_backup: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisantonellis/mongobar/HEAD/assets/psd/help_backup -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | htmlcov/ 3 | dist/ 4 | 5 | .DS_Store 6 | *.py[cod] 7 | .coverage 8 | *.egg-info/ 9 | .notes -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "3.6" 4 | install: 5 | - pip install .[tests] 6 | - pip install coveralls 7 | script: green -r 8 | after_success: 9 | coveralls -------------------------------------------------------------------------------- /TODO.txt: -------------------------------------------------------------------------------- 1 | 2 | * better management of manually defined destination connections, should 3 | raise exception if not all required attributes are defined, possibly from 4 | config or connections class 5 | 6 | * update example images -------------------------------------------------------------------------------- /.mongobar_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "log_level": "DEBUG", 3 | "connections": { 4 | "remote": { 5 | "host": "mongobar_remote", 6 | "port": 27017, 7 | "username": "backup_restore_user", 8 | "password": "password", 9 | "authdb": "admin" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /init_auth.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # start mongo without auth 4 | mongod --fork --logpath /var/log/mongodb.log 5 | 6 | # create backup and restore user 7 | mongo admin --eval ' 8 | db.createUser({ 9 | user: "backup_restore_user", 10 | pwd: "password", 11 | roles: [{ 12 | role: "backup", 13 | db: "admin" 14 | },{ 15 | role: "restore", 16 | db: "admin" 17 | }] 18 | })' 19 | 20 | # stop mongo 21 | mongo admin --eval "db.shutdownServer()" 22 | 23 | # start mongo with auth 24 | mongod --fork --logpath /var/log/mongodb.log --auth 25 | 26 | tail -f /dev/null -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.0" 2 | services: 3 | 4 | mongobar_host: 5 | build: . 6 | container_name: mongobar_host 7 | image: mongobar 8 | volumes: 9 | - ./mongobar:/mongobar/mongobar 10 | - ./.mongobar_config.json:/root/.mongobar_config.json 11 | - ./tests:/tests 12 | - ./htmlcov:/htmlcov 13 | 14 | mongobar_remote: 15 | build: . 16 | container_name: mongobar_remote 17 | image: mongobar 18 | environment: 19 | - MONGO_INITDB_ROOT_USERNAME=admin 20 | - MONGO_INITDB_ROOT_PASSWORD=password 21 | command: /init_auth.sh 22 | -------------------------------------------------------------------------------- /mongobar/exceptions.py: -------------------------------------------------------------------------------- 1 | 2 | class BaseError(Exception): 3 | msg = "" 4 | 5 | def __init__(self, *args): 6 | msg = self.msg.format(*args) if args else self.msg 7 | super().__init__(msg) 8 | 9 | 10 | class ServerConnectionError(BaseError): 11 | msg = "Connection error: {}" 12 | 13 | 14 | class ConnectionNotSetError(BaseError): 15 | msg = "Connection '{}' not set" 16 | 17 | 18 | class ConnectionAttributeNotSetError(BaseError): 19 | msg = "Connection attribute '{}' not set" 20 | 21 | 22 | class BackupNotFoundError(BaseError): 23 | msg = "Backup '{}' not found" 24 | 25 | 26 | class CommandError(BaseError): 27 | msg = "Command failed: {}" 28 | 29 | 30 | class DatabaseNotFoundInBackupError(BaseError): 31 | msg = "Database '{}' not found in backup '{}'" 32 | 33 | 34 | class CollectionNotFoundInBackupError(BaseError): 35 | msg = "Collection '{}' not found in database '{}' in backup '{}'" 36 | 37 | 38 | class DestinationDatabasesLengthError(BaseError): 39 | msg = "Number of databases ({}) and destination databases ({}) must match." 40 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Christopher Antonellis 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # debian & python3.6 2 | FROM python:3.6 3 | 4 | # set timezone 5 | RUN echo "US/Eastern" > /etc/timezone 6 | RUN dpkg-reconfigure -f noninteractive tzdata 7 | 8 | # add mongodb to sources list 9 | RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6 10 | RUN echo "deb http://repo.mongodb.org/apt/debian jessie/mongodb-org/3.4 main" | tee /etc/apt/sources.list.d/mongodb-org-3.4.list 11 | RUN apt-get update && apt-get -y upgrade 12 | 13 | # nano editor 14 | RUN apt-get install nano 15 | 16 | # mongodb 17 | RUN apt-get install -y mongodb-org 18 | RUN mkdir -p /data/db 19 | 20 | # add mongobar 21 | ADD ./mongobar /mongobar/mongobar 22 | ADD ./setup.py /mongobar/setup.py 23 | ADD ./.mongobar_config.json /root/.mongobar_config.json 24 | 25 | # install mongobar 26 | WORKDIR /mongobar 27 | RUN pip install -e .[tests] 28 | 29 | # add tests 30 | ADD ./tests /tests 31 | 32 | # add init scripts 33 | WORKDIR / 34 | 35 | # ADD ./init.sh /init.sh 36 | ADD ./init_auth.sh /init_auth.sh 37 | 38 | # RUN chmod 775 /init.sh 39 | RUN chmod 775 /init_auth.sh 40 | 41 | # run forevz bby 42 | CMD ["mongod"] 43 | -------------------------------------------------------------------------------- /mongobar/utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | import copy 3 | 4 | 5 | def _merge(a, b): 6 | """ a overwrites values in b 7 | """ 8 | 9 | for k in a.keys(): 10 | if isinstance(a[k], dict) and k in b and isinstance(b[k], dict): 11 | b[k] = _merge(a[k], b[k]) 12 | else: 13 | b[k] = a[k] 14 | return b 15 | 16 | 17 | def merge(a, b): 18 | """ makes copies before merging 19 | """ 20 | 21 | return _merge(copy.deepcopy(a), copy.deepcopy(b)) 22 | 23 | 24 | def get_directories(path): 25 | """ returns a list of directory names from `path` 26 | """ 27 | 28 | try: 29 | directories = [] 30 | for directory in os.listdir(path): 31 | directory_path = os.path.join(path, directory) 32 | if os.path.isdir(directory_path): 33 | directories.append(directory) 34 | 35 | except Exception as e: 36 | # TODO: handle exception 37 | # TODO: logging, raise FileNotFoundError, PermissionError 38 | raise 39 | 40 | return directories 41 | 42 | 43 | def create_directory(path): 44 | """ creates a directory at `path` 45 | """ 46 | 47 | try: 48 | os.makedirs(path) 49 | 50 | except Exception as e: 51 | # TODO: handle exception 52 | # TODO: logging, raise FileNotFoundError, PermissionError 53 | raise 54 | 55 | return True 56 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import io 2 | import os 3 | import sys 4 | import shutil 5 | import subprocess 6 | import setuptools 7 | 8 | # read module version file 9 | setup_abs_path = os.path.abspath(os.path.dirname(__file__)) 10 | version_abs_path = os.path.join(setup_abs_path, "mongobar", "__version__.py") 11 | module_metadata = {} 12 | with open(version_abs_path) as file_handle: 13 | exec(file_handle.read(), module_metadata) 14 | 15 | 16 | setuptools.setup( 17 | name="mongobar", 18 | version=module_metadata["__version__"], 19 | description="MongoDB Backup and Restore manager", 20 | keywords="mongodb backup restore mongodump mongorestore", 21 | url="https://github.com/chrisantonellis/mongobar", 22 | 23 | author="Christopher Antonellis", 24 | author_email="christopher.antonellis@gmail.com", 25 | license="MIT", 26 | packages=[ 27 | "mongobar" 28 | ], 29 | # https://stackoverflow.com/a/5899643/1671562 30 | package_data={ 31 | "mongobar": [ 32 | "data/nouns.txt", 33 | "data/verbs.txt" 34 | ] 35 | }, 36 | scripts=[ 37 | "mongobar/scripts/mongobar" 38 | ], 39 | install_requires=[ 40 | "pymongo", 41 | "colorama", 42 | "terminaltables", 43 | "python-dateutil" 44 | ], 45 | extras_require={ 46 | "tests": [ 47 | "green", 48 | "coverage" 49 | ], 50 | }, 51 | classifiers=[ 52 | "Development Status :: 3 - Alpha", 53 | "Environment :: Console", 54 | "Intended Audience :: Developers", 55 | "License :: OSI Approved :: MIT License", 56 | "Natural Language :: English", 57 | "Programming Language :: Python :: 3", 58 | "Programming Language :: Python :: 3.6", 59 | "Topic :: Database :: Front-Ends", 60 | "Topic :: Software Development" 61 | ] 62 | ) 63 | -------------------------------------------------------------------------------- /tests/test_config.py: -------------------------------------------------------------------------------- 1 | import sys; sys.path.append("../") # noqa 2 | import unittest 3 | import logging 4 | import os 5 | 6 | from unittest import mock 7 | 8 | from mongobar.config import Config 9 | from mongobar.connection import Connections 10 | 11 | 12 | mocked_config_1 = { 13 | "root": "/backups", 14 | "connections": { 15 | "default": { 16 | "host": "localhost", 17 | "port": 27017 18 | } 19 | } 20 | } 21 | 22 | mocked_config_2 = { 23 | "log_level": "DEBUG", 24 | "connections": { 25 | "custom": { 26 | "host": "custom", 27 | "port": 27017 28 | } 29 | } 30 | } 31 | 32 | # Test Config 33 | 34 | class TestConfig(unittest.TestCase): 35 | 36 | # init 37 | 38 | def test____init____no_args(self): 39 | m = Config() 40 | self.assertIsInstance(m.connections, Connections) 41 | self.assertEqual(m.configs, [m.default_config]) 42 | self.assertIsInstance(m.logger, logging.Logger) 43 | 44 | # add_data 45 | 46 | def test__add_data(self): 47 | m = Config() 48 | m.add(mocked_config_1) 49 | self.assertEqual(m.configs, [m.default_config, mocked_config_1]) 50 | 51 | # add_file 52 | 53 | @mock.patch("builtins.open", new_callable=mock.mock_open) 54 | @mock.patch("mongobar.mongobar.json.loads", return_value=mocked_config_1) 55 | def test__add_file(self, loads, open_): 56 | m = Config() 57 | m.add_file("/file.json") 58 | open_.assert_called_with("/file.json") 59 | self.assertEqual(m.configs, [m.default_config, mocked_config_1]) 60 | 61 | @mock.patch("builtins.open", new_callable=mock.mock_open) 62 | @mock.patch("mongobar.mongobar.json.loads", side_effect=Exception()) 63 | def test__add_file__does_not_raise_exception(self, loads, open_): 64 | m = Config() 65 | m.add_file("/file.json") 66 | 67 | # root 68 | 69 | def test__root_property(self): 70 | m = Config() 71 | self.assertEqual(m.root, os.path.expanduser(m.config.get("root"))) 72 | 73 | # log_level 74 | 75 | def test__log_level_property(self): 76 | m = Config() 77 | self.assertEqual(m.log_level, "INFO") 78 | 79 | # log_file 80 | 81 | def test__log_file_property(self): 82 | m = Config() 83 | m.add({"log_file": "/logfile"}) 84 | self.assertEqual(m.log_file, "/logfile") 85 | -------------------------------------------------------------------------------- /mongobar/config.py: -------------------------------------------------------------------------------- 1 | import os 2 | import logging 3 | import json 4 | import copy 5 | 6 | from mongobar.connection import Connection 7 | from mongobar.connection import Connections 8 | from mongobar.exceptions import ConnectionNotSetError 9 | from mongobar.utils import merge 10 | 11 | 12 | class Config(object): 13 | 14 | default_connection = "default" 15 | default_config = { 16 | "root": "~/.mongobar_backups", 17 | "log_level": "INFO", 18 | "connections": { 19 | "default": { 20 | "host": "localhost", 21 | "port": 27017 22 | } 23 | } 24 | } 25 | 26 | def __init__(self): 27 | self.logger = logging.getLogger("mongobar_config") 28 | self._connection = self.default_connection 29 | self.connections = Connections() 30 | self.configs = [self.default_config] 31 | self.config = {} 32 | self.merge() 33 | 34 | @property 35 | def connection(self): 36 | return self.connections.get(self._connection) 37 | 38 | @connection.setter 39 | def connection(self, value): 40 | self._connection = value 41 | 42 | @property 43 | def connection_dir(self): 44 | return os.path.join(self.root, self.connection.socket) 45 | 46 | @property 47 | def root(self): 48 | return os.path.expanduser(self.config.get("root")) 49 | 50 | @property 51 | def log_level(self): 52 | return self.config.get("log_level", None) 53 | 54 | @property 55 | def log_file(self): 56 | return self.config.get("log_file", None) 57 | 58 | def add(self, data): 59 | self.configs.append(data) 60 | self.merge() 61 | 62 | def add_file(self, config_file): 63 | try: 64 | with open(os.path.expanduser(config_file)) as file_handle: 65 | self.add(json.loads(file_handle.read())) 66 | self.merge() 67 | except Exception as e: 68 | # print(e) 69 | pass 70 | 71 | def merge(self): 72 | data = {} 73 | 74 | # merge configs 75 | for layer in self.configs: 76 | data = merge(layer, data) 77 | self.config = copy.deepcopy(data) 78 | 79 | # create connections 80 | self.connections.connections = {} 81 | for name, attributes in data["connections"].items(): 82 | self.connections.add(name, attributes) 83 | -------------------------------------------------------------------------------- /tests/test_utils.py: -------------------------------------------------------------------------------- 1 | 2 | import sys; sys.path.append("../") # noqa 3 | import unittest 4 | import os 5 | import subprocess 6 | 7 | from unittest import mock 8 | 9 | import mongobar.utils as utils 10 | 11 | 12 | # Test Utility Methods 13 | 14 | class TestUtils(unittest.TestCase): 15 | 16 | # _merge 17 | 18 | def test___merge(self): 19 | input_1 = {"a": "v"} 20 | input_2 = {"b": "v"} 21 | output = utils._merge(input_1, input_2) 22 | expected_output = {"a": "v", "b": "v"} 23 | 24 | self.assertEqual(output, expected_output) 25 | self.assertEqual(input_2, expected_output) 26 | 27 | def test___merge__recursive(self): 28 | input_1 = {"a": {"b": "v1"}} 29 | input_2 = {"a": {"b": "v2"}} 30 | output = utils._merge(input_1, input_2) 31 | expected_output = {"a": {"b": "v1"}} 32 | 33 | self.assertEqual(output, expected_output) 34 | self.assertEqual(input_2, expected_output) 35 | 36 | # merge 37 | 38 | def test__merge(self): 39 | input_1 = {"a": "v"} 40 | input_2 = {"b": "v"} 41 | output = utils.merge(input_1, input_2) 42 | expected_output = {"a": "v", "b": "v"} 43 | 44 | self.assertEqual(output, expected_output) 45 | self.assertNotEqual(input_2, expected_output) 46 | 47 | 48 | # get_directories 49 | 50 | @mock.patch("mongobar.utils.os.path.isdir", return_value=True) 51 | @mock.patch("mongobar.utils.os.listdir", return_value=["subdirectory"]) 52 | def test___get_directories(self, listdir, isdir): 53 | utils.get_directories("test") 54 | listdir.assert_called_with("test") 55 | isdir.assert_called_with("test/subdirectory") 56 | 57 | @mock.patch("mongobar.utils.os.path.isdir", return_value=True) 58 | @mock.patch("mongobar.utils.os.listdir", side_effect=Exception()) 59 | def test___get_directories__raises_Exception(self, listdir, isdir): 60 | with self.assertRaises(Exception): 61 | utils.get_directories("test") 62 | 63 | # create_directory 64 | 65 | @mock.patch("mongobar.utils.os.makedirs", return_value=True) 66 | def test___create_directory(self, makedirs): 67 | utils.create_directory("test/subdirectory/") 68 | makedirs.assert_called_with("test/subdirectory/") 69 | 70 | @mock.patch("mongobar.utils.os.makedirs", side_effect=Exception()) 71 | def test___create_directory__raises_Exception(self, makedirs): 72 | with self.assertRaises(Exception): 73 | utils.create_directory("test/subdirectory/") 74 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/) 5 | and this project adheres to [Semantic Versioning](http://semver.org/). 6 | 7 | ## [ 0.0.13 ] 2017-12-31 8 | 9 | ### Added 10 | * `--noIndexRestore` flag to `mongorestore` command, blah 11 | 12 | ## [ 0.0.12 ] 2017-11-28 13 | 14 | ### Changed 15 | * updated tests 16 | * bug fixed when specifying `--port` flag with custom port number. 17 | ([Issue #1](https://github.com/chrisantonellis/mongobar/issues/1)) 18 | 19 | ## [ 0.0.11 ] 2017-10-05 20 | 21 | ### Changed 22 | * fixed issue with restore and connection mapping 23 | 24 | ## [ 0.0.10 ] 2017-10-05 25 | 26 | ### Changed 27 | * fixed issue with restore when a destination connection is not specified 28 | 29 | ## [ 0.0.9 ] 2017-10-03 30 | 31 | ### Added 32 | * TODO.txt 33 | * get() method to Connection class 34 | 35 | ### Changed 36 | 37 | * removed 'argcomplete' from pip requirements 38 | * fixed bug with specifying destination connection 39 | 40 | ## [ 0.0.8 ] 2017-09-21 41 | 42 | ### Added 43 | 44 | * clean parser exit on 'backup not found' 45 | 46 | ### Changed 47 | 48 | * fixed bug with removing a backup 49 | * renamed 'hosts' action to 'dirs' to match 'connection directory' naming 50 | * renamed get_hosts method to get_connection_directories in Mongobar class 51 | * changed formatted connection name color from MAGENTA to YELLOW 52 | 53 | ## [ 0.0.7 ] 2017-09-18 54 | 55 | ### Added 56 | 57 | * colored loglevels using Colorama for stream logging handler 58 | 59 | ### Changed 60 | 61 | * main parser name adjusted 62 | * setup.py description adjusted 63 | * MongobarScript.capture_multiline_input fixed 64 | * MongobarScript.capture_multiline_input exceptions captured correctly 65 | * logger.warn calls changed to logger.warning due to deprecation notice from unittest 66 | * fixed param name bug with calling restore 67 | * fixed bug with determining destination connection on restore 68 | 69 | ## [ 0.0.6 ] 2017-09-06 70 | 71 | ### Added 72 | 73 | * Connection.validate method 74 | * integrated into tests 75 | * integrated into Connections.add method 76 | * updated test_mongobar tests to get to 100% coverage 77 | 78 | ## [ 0.0.5 ] 2017-09-06 79 | 80 | ### Added 81 | 82 | * CHANGELOG.MD 83 | * .travis.yml 84 | 85 | ### Changed 86 | 87 | * version moved from __init__.py to __version__.py 88 | * setup.py updated to use __version__.py 89 | * tests updated to work in travis environment 90 | * added badges to README.md 91 | 92 | ## [ 0.0.4 ] 2017-09-02 93 | 94 | ### Added 95 | * initial release 96 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## mongobar [![Build Status](https://travis-ci.org/chrisantonellis/mongobar.svg?branch=master)](https://travis-ci.org/chrisantonellis/mongobar) [![Coverage Status](https://coveralls.io/repos/github/chrisantonellis/mongobar/badge.svg?branch=master)](https://coveralls.io/github/chrisantonellis/mongobar?branch=master) 2 | ![](assets/backups.png) 3 | mongobar is a python shell script used to create and manage MongoDB backups. Internally it is a wrapper for the MongoDB **mongodump** and **mongorestore** commands. 4 | 5 | ## Installation 6 | ``` 7 | pip install mongobar 8 | ``` 9 | ## Usage 10 | Run `mongobar` in a terminal 11 | 12 | ## Help 13 | Access help via the `-h --help` commands. All actions have associated help text. 14 | 15 | `mongobar --help` 16 | ![mongobar --help](assets/help.png) 17 | `mongobar backup --help` 18 | ![mongobar --help](assets/help_backup.png) 19 | 20 | ## Configuration 21 | mongobar comes with a default configuration that defines a `Connection` for a MongoDB server running on **localhost:27017** with authentication disabled. Here is what that config looks like: 22 | ```json 23 | { 24 | "root": "~/.mongobar_backups", 25 | "log_level": "INFO", 26 | "connections": { 27 | "default": { 28 | "host": "localhost", 29 | "port": 27017 30 | } 31 | } 32 | } 33 | ``` 34 | The `default` connection can be overridden and additional connections can be added by writing a config file. Here is an example of a custom config: 35 | ```json 36 | { 37 | "connections": { 38 | "default": { 39 | "host": "localhost", 40 | "port": 27017, 41 | "username": "user", 42 | "password": "pass", 43 | "authdb": "admin" 44 | }, 45 | "production": { 46 | "host": "102.100.204.35", 47 | "port": 27017, 48 | "username": "user", 49 | "password": "pass", 50 | "authdb": "admin" 51 | } 52 | } 53 | } 54 | ``` 55 | mongobar will try to load a config file from `~/.mongobar_config.json` by default. This path can be changed by using the `--config` flag. The current configuration can be viewed by running the `config` action. 56 | 57 | ## Connections 58 | mongobar uses the `connection` action to view and set the **current connection**. This attribute is used by actions `backup`, `restore`, `remove`, `backups`, `hosts`, and `meta`. Connections are defined in the configuration file and can be viewed by running the `config` action. 59 | 60 | 81 | -------------------------------------------------------------------------------- /mongobar/connection.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from mongobar.exceptions import ConnectionNotSetError 4 | from mongobar.exceptions import ConnectionAttributeNotSetError 5 | 6 | 7 | class Connection(object): 8 | 9 | def __init__(self, name, host=None, port=None, \ 10 | username=None, password=None, authdb=None): 11 | self.name = name 12 | self.host = host 13 | self.port = port 14 | self.username = username 15 | self.password = password 16 | self.authdb = authdb 17 | 18 | def validate(self): 19 | 20 | # host 21 | if self.host is None: 22 | raise ConnectionAttributeNotSetError("host") 23 | 24 | # port 25 | if self.port is None: 26 | raise ConnectionAttributeNotSetError("port") 27 | 28 | # username, password 29 | if self.username is not None or self.password is not None: 30 | 31 | if self.username is None: 32 | raise ConnectionAttributeNotSetError("username") 33 | 34 | if self.password is None: 35 | raise ConnectionAttributeNotSetError("password") 36 | 37 | return True 38 | 39 | @property 40 | def socket(self): 41 | return "{}:{}".format(self.host, self.port) 42 | 43 | @property 44 | def auth(self): 45 | return bool(self.username and self.password) 46 | 47 | def get(self): 48 | 49 | self.validate() 50 | 51 | data = { 52 | "host": self.host, 53 | "port": self.port 54 | } 55 | 56 | if self.username is not None: 57 | data["username"] = self.username 58 | data["password"] = self.password 59 | 60 | if self.authdb is not None: 61 | data["authdb"] = self.authdb 62 | 63 | return data 64 | 65 | 66 | class Connections(object): 67 | 68 | def __init__(self): 69 | self.connections = {} 70 | 71 | def names(self, **kwargs): 72 | return [c for c in self.connections.keys()] 73 | 74 | def add(self, name, data): 75 | self.connections[name] = Connection( 76 | name, 77 | data.get("host"), 78 | data.get("port"), 79 | data.get("username", None), 80 | data.get("password", None), 81 | data.get("authdb", None) 82 | ) 83 | 84 | def get(self, name=None, socket=None): 85 | 86 | # get by name 87 | if name is not None: 88 | if name not in self.connections: 89 | raise ConnectionNotSetError(name) 90 | 91 | connection = self.connections[name] 92 | connection.validate() 93 | return connection 94 | 95 | # get by socket 96 | if socket is not None: 97 | for connection in self.connections.values(): 98 | if connection.socket == socket: 99 | 100 | connection.validate() 101 | return connection 102 | -------------------------------------------------------------------------------- /tests/test_connection.py: -------------------------------------------------------------------------------- 1 | import sys; sys.path.append("../") # noqa 2 | import unittest 3 | import logging 4 | 5 | from unittest import mock 6 | 7 | from mongobar.connection import Connection 8 | from mongobar.connection import Connections 9 | 10 | from mongobar.exceptions import ConnectionNotSetError 11 | from mongobar.exceptions import ConnectionAttributeNotSetError 12 | 13 | 14 | # Test Connection 15 | 16 | class TestConnection(unittest.TestCase): 17 | 18 | # validate 19 | 20 | def test__validate(self): 21 | c = Connection( 22 | name="default", 23 | host="localhost", 24 | port=27017 25 | ) 26 | 27 | self.assertTrue(c.validate()) 28 | 29 | def test__validate__auth_args(self): 30 | c = Connection( 31 | name="default", 32 | host="localhost", 33 | port=27017, 34 | username="username", 35 | password="password", 36 | authdb="authdb" 37 | ) 38 | 39 | self.assertTrue(c.validate()) 40 | 41 | def test__validate__missing_host__raises__ConnectionAttributeNotSetError(self): 42 | c = Connection( 43 | name="default", 44 | port=27017 45 | ) 46 | 47 | with self.assertRaises(ConnectionAttributeNotSetError): 48 | c.validate() 49 | 50 | def test__validate__missing_port__raises__ConnectionAttributeNotSetError(self): 51 | c = Connection( 52 | name="default", 53 | host="localhost" 54 | ) 55 | 56 | with self.assertRaises(ConnectionAttributeNotSetError): 57 | c.validate() 58 | 59 | def test__validate__missing_username__raises__ConnectionAttributeNotSetError(self): 60 | c = Connection( 61 | name="default", 62 | host="localhost", 63 | port=27017, 64 | password="pass" 65 | ) 66 | 67 | with self.assertRaises(ConnectionAttributeNotSetError): 68 | c.validate() 69 | 70 | def test__validate__missing_password__raises__ConnectionAttributeNotSetError(self): 71 | c = Connection( 72 | name="default", 73 | host="localhost", 74 | port=27017, 75 | username="user" 76 | ) 77 | 78 | with self.assertRaises(ConnectionAttributeNotSetError): 79 | c.validate() 80 | 81 | # socket 82 | 83 | def test__socket_property(self): 84 | c = Connection( 85 | name="default", 86 | host="localhost", 87 | port=27017 88 | ) 89 | 90 | self.assertEqual(c.socket, "localhost:27017") 91 | 92 | # auth 93 | 94 | def test__auth__returns_False(self): 95 | c = Connection( 96 | name="default", 97 | host="localhost", 98 | port=27017 99 | ) 100 | 101 | self.assertFalse(c.auth) 102 | 103 | def test__auth__returns_True(self): 104 | c = Connection( 105 | name="default", 106 | host="localhost", 107 | port=27017, 108 | username="user", 109 | password="password", 110 | ) 111 | 112 | self.assertTrue(c.auth) 113 | 114 | 115 | class TestConnections(unittest.TestCase): 116 | 117 | def test____init____no_args(self): 118 | c = Connections() 119 | self.assertEqual(c.connections, {}) 120 | 121 | def test__names(self): 122 | c = Connections() 123 | c.add("foo", {"host": "bar", "port": 27017}) 124 | c.add("bar", {"host": "bar", "port": 27017}) 125 | self.assertEqual(c.names(), ["foo", "bar"]) 126 | 127 | def test__add(self): 128 | c = Connections() 129 | c.add("foo", {"host": "bar", "port": 27017}) 130 | self.assertEqual(c.connections["foo"].name, "foo") 131 | self.assertEqual(c.connections["foo"].host, "bar") 132 | self.assertEqual(c.connections["foo"].port, 27017) 133 | 134 | def test__get__name_arg(self): 135 | c = Connections() 136 | c.add("foobar", {"host": "localhost", "port": 27017}) 137 | connection = c.get("foobar") 138 | self.assertEqual(connection.host, "localhost") 139 | self.assertEqual(connection.port, 27017) 140 | 141 | def test__get__name_arg__raises_ConnectionNotSetError(self): 142 | c = Connections() 143 | with self.assertRaises(ConnectionNotSetError): 144 | c.get("foobar") 145 | 146 | def test__get__socket_arg(self): 147 | c = Connections() 148 | c.add("foobar", {"host": "localhost", "port": 27017}) 149 | self.assertEqual(c.get(socket="localhost:27017").name, "foobar") 150 | -------------------------------------------------------------------------------- /mongobar/mongobar.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import logging 4 | import pkgutil 5 | import random 6 | import pymongo 7 | import datetime 8 | import copy 9 | import json 10 | import subprocess 11 | import shutil 12 | 13 | from mongobar.utils import create_directory 14 | from mongobar.utils import get_directories 15 | 16 | from mongobar.config import Config 17 | 18 | from mongobar.exceptions import ServerConnectionError 19 | from mongobar.exceptions import CommandError 20 | from mongobar.exceptions import BackupNotFoundError 21 | from mongobar.exceptions import DatabaseNotFoundInBackupError 22 | from mongobar.exceptions import CollectionNotFoundInBackupError 23 | from mongobar.exceptions import DestinationDatabasesLengthError 24 | 25 | 26 | class Mongobar(object): 27 | 28 | def __init__(self): 29 | self.logger = logging.getLogger("mongobar") 30 | self.config = Config() 31 | 32 | def generate_backup_name(self): 33 | 34 | # TODO: try, catch for potential get_data errors like returning None 35 | # https://docs.python.org/2/library/pkgutil.html#pkgutil.get_data 36 | 37 | verbs_bytes = pkgutil.get_data("mongobar", "data/verbs.txt") 38 | verbs = verbs_bytes.decode("utf-8").split("\n") 39 | verb = random.choice(verbs) 40 | 41 | # get random noun 42 | nouns_bytes = pkgutil.get_data("mongobar", "data/nouns.txt") 43 | nouns = nouns_bytes.decode("utf-8").split("\n") 44 | noun = random.choice(nouns) 45 | 46 | return "{}-{}".format(verb, noun) 47 | 48 | def create_pymongo_client(self): 49 | 50 | connection = self.config.connection 51 | 52 | options = { 53 | "host": connection.host, 54 | "port": connection.port 55 | } 56 | 57 | if connection.auth: 58 | options["username"] = connection.username 59 | options["password"] = connection.password 60 | if connection.authdb is not None: 61 | options["authSource"] = connection.authdb 62 | 63 | try: 64 | client = pymongo.MongoClient(**options) 65 | 66 | # test connection 67 | client.database_names() 68 | 69 | return client 70 | 71 | except pymongo.errors.PyMongoError as e: 72 | raise ServerConnectionError(e) 73 | 74 | def generate_metadata(self, databases=None, collections=None): 75 | 76 | connection = self.config.connection 77 | client = self.create_pymongo_client() 78 | 79 | metadata = { 80 | "host": connection.host, 81 | "port": connection.port, 82 | "date": datetime.datetime.today().isoformat(), 83 | "databases": [] 84 | } 85 | 86 | dbs = databases or client.database_names() 87 | if "local" in dbs: 88 | dbs.remove("local") 89 | 90 | for db in dbs: 91 | db_metadata = { 92 | "name": db, 93 | "collections": [] 94 | } 95 | 96 | for collection in collections or client[db].collection_names(): 97 | db_metadata["collections"].append({ 98 | "name": collection, 99 | "document_count": client[db][collection].count() 100 | }) 101 | 102 | if db_metadata["collections"]: 103 | metadata["databases"].append(db_metadata) 104 | 105 | client.close() 106 | 107 | return metadata 108 | 109 | def write_metadata(self, name, data): 110 | 111 | metadata_path = os.path.join( 112 | self.config.connection_dir, 113 | name, 114 | "metadata.json" 115 | ) 116 | 117 | with open(metadata_path, "w+") as file_handle: 118 | json.dump(data, file_handle) 119 | 120 | return True 121 | 122 | def read_metadata(self, name): 123 | 124 | connection = self.config.connection 125 | 126 | metadata_path = os.path.join( 127 | self.config.connection_dir, 128 | name, 129 | "metadata.json" 130 | ) 131 | 132 | try: 133 | with open(metadata_path, "r") as file_handle: 134 | metadata = json.loads(file_handle.read()) 135 | 136 | except FileNotFoundError: 137 | metadata = { 138 | "host": connection.host, 139 | "port": connection.port, 140 | "date": "0001-01-01T00:00:00.0000", 141 | "databases": [], 142 | "message": "Metadata not found" 143 | } 144 | 145 | return metadata 146 | 147 | def backup(self, message=None, databases=None, collections=None): 148 | 149 | # create root directory if necessary 150 | root_dir = self.config.root 151 | if not os.path.exists(root_dir): 152 | self.logger.debug("Root directory '{}' created".format(root_dir)) 153 | create_directory(root_dir) 154 | 155 | # create backup directory if necessary 156 | conn_dir = self.config.connection_dir 157 | if not os.path.exists(conn_dir): 158 | self.logger.debug("Backup directory '{}' created".format(conn_dir)) 159 | create_directory(conn_dir) 160 | 161 | # generate unique backup name 162 | while 1: 163 | backup_name = self.generate_backup_name() 164 | if backup_name not in get_directories(conn_dir): 165 | break 166 | 167 | # create backup directory 168 | backup_dir = os.path.join(conn_dir, backup_name) 169 | create_directory(backup_dir) 170 | 171 | # pymongo client 172 | client = self.create_pymongo_client() 173 | 174 | # determine dbs 175 | all_databases = client.database_names() 176 | dbs = databases or all_databases 177 | if "local" in dbs: 178 | dbs.remove("local") 179 | 180 | # generate metadata 181 | metadata = self.generate_metadata(dbs, collections) 182 | metadata["name"] = backup_name 183 | metadata["message"] = message 184 | self.write_metadata(backup_dir, metadata) 185 | 186 | # get connection 187 | conn = self.config.connection 188 | 189 | for db in dbs: 190 | 191 | if db not in all_databases: 192 | msg = "Database '{}' does not exist" 193 | msg = msg.format(db) 194 | self.logger.warning(msg) 195 | 196 | command = ["mongodump"] 197 | command += ["--host", conn.host] 198 | command += ["--port", str(conn.port)] 199 | 200 | if conn.auth: 201 | command += ["-u", conn.username] 202 | command += ["-p", conn.password] 203 | if conn.authdb is not None: 204 | command += ["--authenticationDatabase", conn.authdb] 205 | 206 | command += ["--db", db] 207 | 208 | command_end = ["--out", backup_dir] 209 | command_end += ["--quiet"] 210 | command_end += ["--gzip"] 211 | 212 | # call command once per datbase 213 | if not collections: 214 | command += command_end 215 | 216 | try: 217 | subprocess.check_output(command) 218 | self.logger.debug("Command called: {}".format(" ".join(command))) 219 | except subprocess.CalledProcessError as e: 220 | raise CommandError(e) 221 | 222 | # call command once per collection 223 | else: 224 | all_collections = client[db].collection_names() 225 | 226 | for col in collections: 227 | 228 | if col not in all_collections: 229 | msg = "Collection '{}' does not exist in database '{}'" 230 | msg = msg.format(col, db) 231 | self.logger.warning(msg) 232 | 233 | col_command = copy.copy(command) 234 | col_command += ["--collection", col] 235 | col_command += command_end 236 | 237 | try: 238 | subprocess.check_output(col_command) 239 | self.logger.debug("Command called: {}".format(" ".join(col_command))) 240 | except subprocess.CalledProcessError as e: 241 | raise CommandError(e) 242 | 243 | return backup_name 244 | 245 | def restore(self, name, databases=None, collections=None, \ 246 | destination_databases=None, destination_connection=None): 247 | 248 | # check if backup directory exists 249 | backup_dir = os.path.join(self.config.connection_dir, name) 250 | if not os.path.exists(backup_dir): 251 | raise BackupNotFoundError(name) 252 | 253 | # read backup metadata 254 | metadata = self.read_metadata(name) 255 | 256 | # check databases against metadata 257 | if databases: 258 | for database in databases: 259 | if database not in [d["name"] for d in metadata["databases"]]: 260 | raise DatabaseNotFoundInBackupError(database, name) 261 | 262 | # check collections against metadata 263 | if collections: 264 | for database in metadata["databases"]: 265 | for collection in collections: 266 | if collection not in [c["name"] for c in database["collections"]]: 267 | raise CollectionNotFoundInBackupError(database, collection, name) 268 | 269 | # check destination databases against databases 270 | if destination_databases: 271 | databases_len = len(databases or metadata["databases"]) 272 | destination_databases_len = len(destination_databases) 273 | if databases_len != destination_databases_len: 274 | raise DestinationDatabasesLengthError( 275 | databases_len, 276 | destination_databases_len 277 | ) 278 | 279 | conn = self.config.connection 280 | dest_conn = self.config.connections.get(destination_connection or self.config.connection.name) 281 | 282 | # iterate databases and collections 283 | for i, database in enumerate(databases or [d["name"] for d in metadata["databases"]]): 284 | 285 | # command, host and port 286 | command = ["mongorestore"] 287 | command += ["--host", dest_conn.host] 288 | command += ["--port", str(dest_conn.port)] 289 | 290 | # authentication 291 | if dest_conn.auth: 292 | command += ["-u", dest_conn.username] 293 | command += ["-p", dest_conn.password] 294 | 295 | if dest_conn.authdb is not None: 296 | command += ["--authenticationDatabase", dest_conn.authdb] 297 | 298 | # destination databases 299 | if destination_databases: 300 | command += ["--db", destination_databases[i]] 301 | 302 | # command output 303 | command_out = ["--drop"] 304 | source_dir = copy.copy(backup_dir) 305 | if destination_databases: 306 | source_dir = os.path.join(source_dir, database) 307 | command_out += ["--dir", source_dir] 308 | command_out += ["--gzip"] 309 | command_out += ["--noIndexRestore"] 310 | 311 | if not collections: 312 | 313 | command += ["--nsInclude", "{}.*".format(database)] 314 | command += command_out 315 | 316 | try: 317 | self.logger.debug("Command called: {}".format(" ".join(command))) 318 | subprocess.check_output(command) 319 | except subprocess.CalledProcessError as e: 320 | raise CommandError(e) 321 | 322 | else: 323 | 324 | for collection in collections: 325 | 326 | collection_command = copy.copy(command) 327 | collection_command += ["--nsInclude", "{}.{}".format(database, collection)] 328 | collection_command += command_out 329 | 330 | try: 331 | self.logger.debug("Command called: {}".format(" ".join(collection_command))) 332 | subprocess.check_output(collection_command) 333 | except subprocess.CalledProcessError as e: 334 | raise CommandError(e) 335 | 336 | def get_connection_directories(self, count=False): 337 | if not os.path.exists(self.config.root): 338 | return [] 339 | 340 | directories = [] 341 | for directory in get_directories(self.config.root): 342 | 343 | if count: 344 | path = os.path.join(self.config.root, directory) 345 | backup_count = len(get_directories(path)) 346 | directories.append((directory, backup_count)) 347 | 348 | else: 349 | directories.append(directory) 350 | 351 | return directories 352 | 353 | def get_backups(self): 354 | path = self.config.connection_dir 355 | 356 | if not os.path.exists(path): 357 | return [] 358 | 359 | return get_directories(path) 360 | 361 | def remove_backup(self, name): 362 | path = os.path.join(self.config.connection_dir, name) 363 | 364 | if not os.path.exists(path): 365 | raise BackupNotFoundError(name) 366 | 367 | shutil.rmtree(path) 368 | -------------------------------------------------------------------------------- /tests/test_mongobar.py: -------------------------------------------------------------------------------- 1 | 2 | import sys; sys.path.append("../") # noqa 3 | import unittest 4 | import logging 5 | import os 6 | import subprocess 7 | import datetime 8 | import pymongo 9 | 10 | from unittest import mock 11 | 12 | import mongobar 13 | 14 | 15 | # Mocked Mongo Client 16 | 17 | 18 | class MockedMongoDocument(mock.Mock): 19 | pass 20 | 21 | 22 | class MockedMongoCollection(mock.Mock): 23 | 24 | def __init__(self, *args, **kwargs): 25 | super().__init__(*args, **kwargs) 26 | self._mocked_documents = [ 27 | MockedMongoDocument(), 28 | MockedMongoDocument(), 29 | MockedMongoDocument() 30 | ] 31 | 32 | def count(self): 33 | return len(self._mocked_documents) 34 | 35 | 36 | class MockedMongoDatabase(mock.Mock): 37 | 38 | def __init__(self, *args, **kwargs): 39 | super().__init__(*args, **kwargs) 40 | self._mocked_collections = { 41 | "c1": MockedMongoCollection(), 42 | "c2": MockedMongoCollection(), 43 | "c3": MockedMongoCollection(), 44 | } 45 | 46 | def __getitem__(self, key): 47 | return self._mocked_collections[key] 48 | 49 | def collection_names(self): 50 | return [key for key in self._mocked_collections.keys()] 51 | 52 | 53 | class MockedMongoClient(mock.Mock): 54 | 55 | def __init__(self, *args, **kwargs): 56 | super().__init__(*args, **kwargs) 57 | self._mocked_databases = { 58 | "local": MockedMongoDatabase(), 59 | "d1": MockedMongoDatabase(), 60 | "d2": MockedMongoDatabase(), 61 | "d3": MockedMongoDatabase(), 62 | } 63 | 64 | def __getitem__(self, key): 65 | return self._mocked_databases[key] 66 | 67 | def database_names(self): 68 | return [key for key in self._mocked_databases.keys()] 69 | 70 | 71 | # Mocked Backup Metadata 72 | 73 | 74 | MOCKED_BACKUP_METADATA_1_DB = { 75 | "host": "localhost", 76 | "port": 27017, 77 | "date": datetime.datetime.today().isoformat(), 78 | "databases": [{ 79 | "name": "d1", 80 | "collections": [{ 81 | "name": "c1", 82 | "document_count": 1 83 | },{ 84 | "name": "c2", 85 | "document_count": 1 86 | }, 87 | { 88 | "name": "c3", 89 | "document_count": 1 90 | }] 91 | }] 92 | } 93 | 94 | MOCKED_BACKUP_METADATA_3_DBS = { 95 | "host": "localhost", 96 | "port": 27017, 97 | "date": datetime.datetime.today().isoformat(), 98 | "databases": [{ 99 | "name": "d1", 100 | "collections": [{ 101 | "name": "c1", 102 | "document_count": 1 103 | },{ 104 | "name": "c2", 105 | "document_count": 1 106 | }, 107 | { 108 | "name": "c3", 109 | "document_count": 1 110 | }] 111 | },{ 112 | "name": "d2", 113 | "collections": [{ 114 | "name": "c1", 115 | "document_count": 1 116 | },{ 117 | "name": "c2", 118 | "document_count": 1 119 | }, 120 | { 121 | "name": "c3", 122 | "document_count": 1 123 | }] 124 | },{ 125 | "name": "d3", 126 | "collections": [{ 127 | "name": "c1", 128 | "document_count": 1 129 | },{ 130 | "name": "c2", 131 | "document_count": 1 132 | }, 133 | { 134 | "name": "c3", 135 | "document_count": 1 136 | }] 137 | }] 138 | } 139 | 140 | 141 | # Test Mongobar Package 142 | 143 | 144 | @mock.patch("mongobar.mongobar.pymongo.MongoClient", new_callable=MockedMongoClient) 145 | class TestMongobar(unittest.TestCase): 146 | 147 | @classmethod 148 | def setUpClass(cls): 149 | logging.getLogger("mongobar").addHandler(logging.NullHandler()) 150 | 151 | # generate_backup_name 152 | 153 | @mock.patch("mongobar.mongobar.pkgutil.get_data", side_effect=[b"foo", b"bar"]) 154 | def test__generate_backup_name(self, *args): 155 | name = mongobar.Mongobar().generate_backup_name() 156 | self.assertEqual(name, "foo-bar") 157 | args[0].assert_called() 158 | 159 | # create_pymongo_client 160 | 161 | def test__create_pymongo_client__default_connection(self, mongoclient): 162 | m = mongobar.Mongobar() 163 | m.create_pymongo_client() 164 | mongoclient.assert_called_with( 165 | host="localhost", 166 | port=27017 167 | ) 168 | 169 | def test__create_pymongo_client__custom_connection(self, mongoclient): 170 | m = mongobar.Mongobar() 171 | m.config.add({ 172 | "connections": { 173 | "custom": { 174 | "host": "custom", 175 | "port": 27017 176 | } 177 | } 178 | }) 179 | m.config.connection = "custom" 180 | m.create_pymongo_client() 181 | mongoclient.assert_called_with( 182 | host="custom", 183 | port=27017 184 | ) 185 | 186 | def test__create_pymongo_client__auth_options(self, mongoclient): 187 | m = mongobar.Mongobar() 188 | m.config.add({ 189 | "connections": { 190 | "default": { 191 | "host": "localhost", 192 | "port": 27017, 193 | "username": "user", 194 | "password": "pass", 195 | "authdb": "authdb" 196 | } 197 | } 198 | }) 199 | m.create_pymongo_client() 200 | mongoclient.assert_called_with( 201 | host="localhost", 202 | port=27017, 203 | username="user", 204 | password="pass", 205 | authSource="authdb" 206 | ) 207 | 208 | def test__create_pymongo_client__auth_options(self, mongoclient): 209 | 210 | mongoclient.side_effect = pymongo.errors.PyMongoError() 211 | 212 | m = mongobar.Mongobar() 213 | m.config.add({ 214 | "connections": { 215 | "default": { 216 | "host": "localhost", 217 | "port": 27017, 218 | "username": "user", 219 | "password": "pass", 220 | "authdb": "authdb" 221 | } 222 | } 223 | }) 224 | 225 | with self.assertRaises(mongobar.exceptions.ServerConnectionError): 226 | m.create_pymongo_client() 227 | 228 | # generate_metadata 229 | 230 | def test__generate_metadata__databases_arg(self, mongoclient): 231 | m = mongobar.Mongobar() 232 | 233 | metadata = m.generate_metadata(databases=["d1", "d2", "d3"]) 234 | 235 | self.assertIn("host", metadata) 236 | self.assertIn("port", metadata) 237 | self.assertIn("date", metadata) 238 | self.assertIn("databases", metadata) 239 | 240 | for database in metadata["databases"]: 241 | self.assertIn("name", database) 242 | self.assertIn("collections", database) 243 | 244 | def test__generate_metadata__databases_arg__remove_local(self, mongoclient): 245 | m = mongobar.Mongobar() 246 | metadata = m.generate_metadata(databases=["d1", "d2", "d3", "local"]) 247 | self.assertNotIn("local", metadata["databases"]) 248 | 249 | # write_metadata 250 | 251 | @mock.patch("builtins.open", new_callable=mock.mock_open) 252 | @mock.patch("mongobar.mongobar.json.dump") 253 | def test__write_metadata(self, dump, open_, mongoclient): 254 | m = mongobar.Mongobar() 255 | m.write_metadata("name", {"key": "value"}) 256 | 257 | path = os.path.join( 258 | m.config.connection_dir, 259 | "name", 260 | "metadata.json" 261 | ) 262 | open_.assert_called_with(path, "w+") 263 | 264 | file_handle = open_() 265 | dump.assert_called_with({"key": "value"}, file_handle) 266 | 267 | # read_metadata 268 | 269 | @mock.patch("builtins.open", new_callable=mock.mock_open) 270 | @mock.patch("mongobar.mongobar.json.loads") 271 | def test__read_metadata(self, loads, open_, mongoclient): 272 | 273 | m = mongobar.Mongobar() 274 | m.read_metadata("name") 275 | 276 | path = os.path.join( 277 | m.config.connection_dir, 278 | "name", 279 | "metadata.json" 280 | ) 281 | open_.assert_called_with(path, "r") 282 | 283 | file_handle = open_() 284 | file_handle.read.assert_called() 285 | 286 | loads.assert_called_with("") 287 | 288 | @mock.patch("builtins.open", side_effect=FileNotFoundError()) 289 | @mock.patch("mongobar.mongobar.json.loads") 290 | def test__read_metadata__file_not_found(self, loads, open_, mongoclient): 291 | m = mongobar.Mongobar() 292 | self.assertEqual(m.read_metadata("name"), { 293 | "host": "localhost", 294 | "port": 27017, 295 | "date": "0001-01-01T00:00:00.0000", 296 | "databases": [], 297 | "message": "Metadata not found" 298 | }) 299 | 300 | # backup 301 | 302 | @mock.patch("mongobar.mongobar.os.path.exists", return_value=True) 303 | @mock.patch("mongobar.Mongobar.generate_backup_name", return_value="foo-bar") 304 | @mock.patch("mongobar.mongobar.get_directories", return_value=[]) 305 | @mock.patch("mongobar.mongobar.create_directory", return_value=True) 306 | @mock.patch("mongobar.Mongobar.generate_metadata", return_value=MOCKED_BACKUP_METADATA_1_DB) 307 | @mock.patch("mongobar.Mongobar.write_metadata") 308 | @mock.patch("mongobar.mongobar.subprocess.check_output") 309 | def test__backup(self, check_output, *args): 310 | m = mongobar.Mongobar() 311 | m.backup() 312 | 313 | directory = os.path.join(m.config.connection_dir, "foo-bar") 314 | 315 | self.assertIn( 316 | mock.call([ 317 | "mongodump", 318 | "--host", "localhost", 319 | "--port", "27017", 320 | "--db", "d1", 321 | "--out", directory, 322 | "--quiet", 323 | "--gzip" 324 | ]), 325 | check_output.call_args_list 326 | ) 327 | 328 | @mock.patch("mongobar.mongobar.os.path.exists", side_effect=[False, True]) 329 | @mock.patch("mongobar.Mongobar.generate_backup_name", return_value="foo-bar") 330 | @mock.patch("mongobar.mongobar.get_directories", return_value=[]) 331 | @mock.patch("mongobar.mongobar.create_directory", return_value=True) 332 | @mock.patch("mongobar.Mongobar.generate_metadata", return_value=MOCKED_BACKUP_METADATA_1_DB) 333 | @mock.patch("mongobar.Mongobar.write_metadata") 334 | @mock.patch("mongobar.mongobar.subprocess.check_output") 335 | def test__backup__create_root_directory(self, *args): 336 | m = mongobar.Mongobar() 337 | m.backup() 338 | self.assertIn(mock.call(m.config.root), args[3].call_args_list) 339 | 340 | @mock.patch("mongobar.mongobar.os.path.exists", side_effect=[True, False]) 341 | @mock.patch("mongobar.Mongobar.generate_backup_name", return_value="foo-bar") 342 | @mock.patch("mongobar.mongobar.get_directories", return_value=[]) 343 | @mock.patch("mongobar.mongobar.create_directory", return_value=True) 344 | @mock.patch("mongobar.Mongobar.generate_metadata", return_value=MOCKED_BACKUP_METADATA_1_DB) 345 | @mock.patch("mongobar.Mongobar.write_metadata") 346 | @mock.patch("mongobar.mongobar.subprocess.check_output") 347 | def test__backup__create_host_directory(self, *args): 348 | m = mongobar.Mongobar() 349 | m.backup() 350 | self.assertIn(mock.call(m.config.connection_dir), args[3].call_args_list) 351 | 352 | @mock.patch("mongobar.mongobar.os.path.exists", return_value=False) 353 | @mock.patch("mongobar.Mongobar.generate_backup_name", return_value="foo-bar") 354 | @mock.patch("mongobar.mongobar.get_directories", return_value=[]) 355 | @mock.patch("mongobar.mongobar.create_directory", return_value=True) 356 | @mock.patch("mongobar.Mongobar.generate_metadata", return_value=MOCKED_BACKUP_METADATA_1_DB) 357 | @mock.patch("mongobar.Mongobar.write_metadata") 358 | @mock.patch("mongobar.mongobar.subprocess.check_output") 359 | def test__backup__message_arg(self, *args): 360 | m = mongobar.Mongobar() 361 | m.backup(message="foo") 362 | 363 | # extract metadata arg passed to self.write_metadata 364 | write_metadata_mock = args[1] 365 | write_metadata_calls = write_metadata_mock.call_args_list[0] 366 | write_metadata_args = write_metadata_calls[0] 367 | metadata = write_metadata_args[1] 368 | 369 | self.assertEqual(metadata["message"], "foo") 370 | 371 | @mock.patch("mongobar.mongobar.os.path.exists", return_value=True) 372 | @mock.patch("mongobar.Mongobar.generate_backup_name", return_value="foo-bar") 373 | @mock.patch("mongobar.mongobar.get_directories", return_value=[]) 374 | @mock.patch("mongobar.mongobar.create_directory", return_value=True) 375 | @mock.patch("mongobar.Mongobar.generate_metadata", return_value=MOCKED_BACKUP_METADATA_1_DB) 376 | @mock.patch("mongobar.Mongobar.write_metadata") 377 | @mock.patch("mongobar.mongobar.subprocess.check_output") 378 | def test__backup__auth_args(self, *args): 379 | 380 | m = mongobar.Mongobar() 381 | m.config.add({ 382 | "connections": { 383 | "default": { 384 | "host": "localhost", 385 | "port": 27017, 386 | "username": "user", 387 | "password": "pass", 388 | "authdb": "authdb" 389 | } 390 | } 391 | }) 392 | m.backup() 393 | 394 | self.assertIn( 395 | mock.call([ 396 | "mongodump", 397 | "--host", "localhost", 398 | "--port", "27017", 399 | "-u", "user", 400 | "-p", "pass", 401 | "--authenticationDatabase", "authdb", 402 | "--db", "d1", 403 | "--out", os.path.join(m.config.connection_dir, "foo-bar"), 404 | "--quiet", 405 | "--gzip" 406 | ]), 407 | args[0].call_args_list 408 | ) 409 | 410 | @mock.patch("mongobar.mongobar.os.path.exists", return_value=True) 411 | @mock.patch("mongobar.Mongobar.generate_backup_name", return_value="foo-bar") 412 | @mock.patch("mongobar.mongobar.get_directories", return_value=[]) 413 | @mock.patch("mongobar.mongobar.create_directory", return_value=True) 414 | @mock.patch("mongobar.Mongobar.generate_metadata", return_value=MOCKED_BACKUP_METADATA_1_DB) 415 | @mock.patch("mongobar.Mongobar.write_metadata") 416 | @mock.patch("mongobar.mongobar.subprocess.check_output") 417 | def test__backup__db_does_not_exist__command_called(self, check_output, *args): 418 | 419 | m = mongobar.Mongobar() 420 | m.backup(databases=["foobar"]) 421 | 422 | self.assertIn( 423 | mock.call([ 424 | "mongodump", 425 | "--host", "localhost", 426 | "--port", "27017", 427 | "--db", "foobar", 428 | "--out", os.path.join(m.config.connection_dir, "foo-bar"), 429 | "--quiet", 430 | "--gzip" 431 | ]), 432 | check_output.call_args_list 433 | ) 434 | 435 | @mock.patch("mongobar.mongobar.os.path.exists", return_value=True) 436 | @mock.patch("mongobar.Mongobar.generate_backup_name", return_value="foo-bar") 437 | @mock.patch("mongobar.mongobar.get_directories", return_value=[]) 438 | @mock.patch("mongobar.mongobar.create_directory", return_value=True) 439 | @mock.patch("mongobar.Mongobar.generate_metadata", return_value=MOCKED_BACKUP_METADATA_1_DB) 440 | @mock.patch("mongobar.Mongobar.write_metadata") 441 | @mock.patch("mongobar.mongobar.subprocess.check_output", side_effect=[subprocess.CalledProcessError(1, "")]) 442 | def test__backup__db_arg__raises_CalledProcessError(self, check_output, *args): 443 | m = mongobar.Mongobar() 444 | with self.assertRaises(mongobar.exceptions.CommandError): 445 | m.backup() 446 | 447 | @mock.patch("mongobar.mongobar.os.path.exists", return_value=True) 448 | @mock.patch("mongobar.Mongobar.generate_backup_name", return_value="foo-bar") 449 | @mock.patch("mongobar.mongobar.get_directories", return_value=[]) 450 | @mock.patch("mongobar.mongobar.create_directory", return_value=True) 451 | @mock.patch("mongobar.Mongobar.generate_metadata", return_value=MOCKED_BACKUP_METADATA_1_DB) 452 | @mock.patch("mongobar.Mongobar.write_metadata") 453 | @mock.patch("mongobar.mongobar.subprocess.check_output") 454 | def test__backup__collection_arg(self, check_output, *args): 455 | 456 | m = mongobar.Mongobar() 457 | m.backup(databases=["d1"], collections=["c1"]) 458 | 459 | self.assertIn( 460 | mock.call([ 461 | "mongodump", 462 | "--host", "localhost", 463 | "--port", "27017", 464 | "--db", "d1", 465 | "--collection", "c1", 466 | "--out", os.path.join(m.config.connection_dir, "foo-bar"), 467 | "--quiet", 468 | "--gzip" 469 | ]), 470 | check_output.call_args_list 471 | ) 472 | 473 | @mock.patch("mongobar.mongobar.os.path.exists", return_value=True) 474 | @mock.patch("mongobar.Mongobar.generate_backup_name", return_value="foo-bar") 475 | @mock.patch("mongobar.mongobar.get_directories", return_value=[]) 476 | @mock.patch("mongobar.mongobar.create_directory", return_value=True) 477 | @mock.patch("mongobar.Mongobar.generate_metadata", return_value=MOCKED_BACKUP_METADATA_1_DB) 478 | @mock.patch("mongobar.Mongobar.write_metadata") 479 | @mock.patch("mongobar.mongobar.subprocess.check_output") 480 | def test__backup__collection_does_not_exist__command_called(self, check_output, *args): 481 | 482 | m = mongobar.Mongobar() 483 | m.backup(databases=["d1"], collections=["foobar"]) 484 | 485 | self.assertIn( 486 | mock.call([ 487 | "mongodump", 488 | "--host", "localhost", 489 | "--port", "27017", 490 | "--db", "d1", 491 | "--collection", "foobar", 492 | "--out", os.path.join(m.config.connection_dir, "foo-bar"), 493 | "--quiet", 494 | "--gzip" 495 | ]), 496 | check_output.call_args_list 497 | ) 498 | 499 | 500 | @mock.patch("mongobar.mongobar.os.path.exists", return_value=True) 501 | @mock.patch("mongobar.Mongobar.generate_backup_name", return_value="foo-bar") 502 | @mock.patch("mongobar.mongobar.get_directories", return_value=[]) 503 | @mock.patch("mongobar.mongobar.create_directory", return_value=True) 504 | @mock.patch("mongobar.Mongobar.generate_metadata", return_value=MOCKED_BACKUP_METADATA_1_DB) 505 | @mock.patch("mongobar.Mongobar.write_metadata") 506 | @mock.patch("mongobar.mongobar.subprocess.check_output", side_effect=[subprocess.CalledProcessError(1, "")]) 507 | def test__backup__collection_arg__raises_CalledProcessError(self, check_output, *args): 508 | m = mongobar.Mongobar() 509 | with self.assertRaises(mongobar.exceptions.CommandError): 510 | m.backup(collections=["foobar"]) 511 | 512 | # restore 513 | 514 | @mock.patch("mongobar.Mongobar.backup") 515 | @mock.patch("mongobar.Mongobar.read_metadata", return_value=MOCKED_BACKUP_METADATA_3_DBS) 516 | @mock.patch("mongobar.mongobar.subprocess.check_output") 517 | @mock.patch("mongobar.mongobar.os.path.exists", return_value=False) 518 | def test__restore__raises_BackupNotFoundError(self, *args): 519 | m = mongobar.Mongobar() 520 | with self.assertRaises(mongobar.exceptions.BackupNotFoundError): 521 | m.restore("foobar") 522 | 523 | @mock.patch("mongobar.Mongobar.backup") 524 | @mock.patch("mongobar.Mongobar.read_metadata", return_value=MOCKED_BACKUP_METADATA_3_DBS) 525 | @mock.patch("mongobar.mongobar.subprocess.check_output") 526 | @mock.patch("mongobar.mongobar.os.path.exists") 527 | def test__restore(self, *args): 528 | m = mongobar.Mongobar() 529 | m.restore("d1") 530 | 531 | directory = os.path.join(m.config.connection_dir, "d1") 532 | 533 | self.assertIn( 534 | mock.call([ 535 | "mongorestore", 536 | "--host", "localhost", 537 | "--port", "27017", 538 | "--nsInclude", "d1.*", 539 | "--drop", 540 | "--dir", directory, 541 | "--gzip" 542 | ]), 543 | args[1].call_args_list 544 | ) 545 | 546 | @mock.patch("mongobar.Mongobar.backup") 547 | @mock.patch("mongobar.Mongobar.read_metadata", return_value=MOCKED_BACKUP_METADATA_3_DBS) 548 | @mock.patch("mongobar.mongobar.subprocess.check_output") 549 | @mock.patch("mongobar.mongobar.os.path.exists") 550 | def test__restore__databases_arg__raises_DatabaseNotFoundInBackupError(self, *args): 551 | m = mongobar.Mongobar() 552 | with self.assertRaises(mongobar.exceptions.DatabaseNotFoundInBackupError): 553 | m.restore("backup", databases=["foobar"]) 554 | 555 | @mock.patch("mongobar.Mongobar.backup") 556 | @mock.patch("mongobar.Mongobar.read_metadata", return_value=MOCKED_BACKUP_METADATA_3_DBS) 557 | @mock.patch("mongobar.mongobar.subprocess.check_output") 558 | @mock.patch("mongobar.mongobar.os.path.exists") 559 | def test__restore__collections_arg__raises_CollectionNotFoundInBackupError(self, *args): 560 | m = mongobar.Mongobar() 561 | with self.assertRaises(mongobar.exceptions.CollectionNotFoundInBackupError): 562 | m.restore("backup", collections=["foobar"]) 563 | 564 | @mock.patch("mongobar.Mongobar.backup") 565 | @mock.patch("mongobar.Mongobar.read_metadata", return_value=MOCKED_BACKUP_METADATA_3_DBS) 566 | @mock.patch("mongobar.mongobar.subprocess.check_output") 567 | @mock.patch("mongobar.mongobar.os.path.exists") 568 | def test__restore__destination_databases_arg__raises_DestinationDatabasesLengthError(self, *args): 569 | m = mongobar.Mongobar() 570 | with self.assertRaises(mongobar.exceptions.DestinationDatabasesLengthError): 571 | m.restore("backup", destination_databases=["foobar"]) 572 | 573 | @mock.patch("mongobar.Mongobar.backup") 574 | @mock.patch("mongobar.Mongobar.read_metadata", return_value=MOCKED_BACKUP_METADATA_3_DBS) 575 | @mock.patch("mongobar.mongobar.subprocess.check_output") 576 | @mock.patch("mongobar.mongobar.os.path.exists") 577 | def test__restore__authentication_options(self, *args): 578 | m = mongobar.Mongobar() 579 | m.config.add({ 580 | "connections": { 581 | "default": { 582 | "host": "localhost", 583 | "port": 27017, 584 | "username": "user", 585 | "password": "pass", 586 | "authdb": "authdb" 587 | } 588 | } 589 | }) 590 | m.restore("backup") 591 | 592 | directory = os.path.join(m.config.connection_dir, "backup") 593 | 594 | self.assertIn( 595 | mock.call([ 596 | "mongorestore", 597 | "--host", "localhost", 598 | "--port", "27017", 599 | "-u", "user", 600 | "-p", "pass", 601 | "--authenticationDatabase", "authdb", 602 | "--nsInclude", "d1.*", 603 | "--drop", 604 | "--dir", directory, 605 | "--gzip" 606 | ]), 607 | args[1].call_args_list 608 | ) 609 | 610 | @mock.patch("mongobar.Mongobar.backup") 611 | @mock.patch("mongobar.Mongobar.read_metadata", return_value=MOCKED_BACKUP_METADATA_3_DBS) 612 | @mock.patch("mongobar.mongobar.subprocess.check_output") 613 | @mock.patch("mongobar.mongobar.os.path.exists") 614 | def test__restore__destination_databases_arg(self, *args): 615 | m = mongobar.Mongobar() 616 | m.restore("backup", databases=["d1"], destination_databases=["destination"]) 617 | 618 | directory = os.path.expanduser("~/.mongobar_backups/localhost:27017/backup/d1") 619 | 620 | args[1].assert_called_with([ 621 | "mongorestore", 622 | "--host", "localhost", 623 | "--port", "27017", 624 | "--db", "destination", 625 | "--nsInclude", "d1.*", 626 | "--drop", 627 | "--dir", directory, 628 | "--gzip" 629 | ]) 630 | 631 | @mock.patch("mongobar.Mongobar.backup") 632 | @mock.patch("mongobar.Mongobar.read_metadata", return_value=MOCKED_BACKUP_METADATA_3_DBS) 633 | @mock.patch("mongobar.mongobar.subprocess.check_output", side_effect=[subprocess.CalledProcessError(1, "")]) 634 | @mock.patch("mongobar.mongobar.os.path.exists") 635 | def test__restore__raises_CommandError(self, *args): 636 | m = mongobar.Mongobar() 637 | with self.assertRaises(mongobar.exceptions.CommandError): 638 | m.restore("backup") 639 | 640 | @mock.patch("mongobar.Mongobar.backup") 641 | @mock.patch("mongobar.Mongobar.read_metadata", return_value=MOCKED_BACKUP_METADATA_3_DBS) 642 | @mock.patch("mongobar.mongobar.subprocess.check_output") 643 | @mock.patch("mongobar.mongobar.os.path.exists") 644 | def test__restore__collection_arg(self, *args): 645 | m = mongobar.Mongobar() 646 | m.restore("backup", collections=["c1"]) 647 | 648 | self.assertIn( 649 | mock.call([ 650 | "mongorestore", 651 | "--host", "localhost", 652 | "--port", "27017", 653 | "--nsInclude", "d1.c1", 654 | "--drop", 655 | "--dir", os.path.join(m.config.connection_dir, "backup"), 656 | "--gzip" 657 | ]), 658 | args[1].call_args_list 659 | ) 660 | 661 | @mock.patch("mongobar.Mongobar.backup") 662 | @mock.patch("mongobar.Mongobar.read_metadata", return_value=MOCKED_BACKUP_METADATA_3_DBS) 663 | @mock.patch("mongobar.mongobar.subprocess.check_output", side_effect=[subprocess.CalledProcessError(1, "")]) 664 | @mock.patch("mongobar.mongobar.os.path.exists") 665 | def test__restore__collection_arg__raises_CommandError(self, *args): 666 | m = mongobar.Mongobar() 667 | 668 | with self.assertRaises(mongobar.exceptions.CommandError): 669 | m.restore("backup", collections=["c1"]) 670 | 671 | # get connection directories 672 | 673 | @mock.patch("mongobar.mongobar.os.path.exists", return_value=False) 674 | @mock.patch("mongobar.mongobar.get_directories", return_value=["d1", "d2"]) 675 | def test__get_hosts__directory_does_not_exist(self, *args): 676 | m = mongobar.Mongobar() 677 | self.assertEqual(m.get_connection_directories(), []) 678 | 679 | @mock.patch("mongobar.mongobar.os.path.exists", return_value=True) 680 | @mock.patch("mongobar.mongobar.get_directories", return_value=["d1", "d2"]) 681 | def test__get_connection_directories__return_names(self, *args): 682 | m = mongobar.Mongobar() 683 | m.get_connection_directories() 684 | args[0].assert_called_with(m.config.root) 685 | 686 | @mock.patch("mongobar.mongobar.os.path.exists", return_value=True) 687 | @mock.patch("mongobar.mongobar.get_directories", side_effect=[["host"],["db"]]) 688 | def test__get_connection_directories__return_names_and_counts(self, *args): 689 | m = mongobar.Mongobar() 690 | m.get_connection_directories(count=True) 691 | 692 | self.assertEqual( 693 | args[0].call_args_list, 694 | [ 695 | mock.call(m.config.root), 696 | mock.call(os.path.join(m.config.root, "host")) 697 | ] 698 | ) 699 | 700 | # list backups 701 | 702 | @mock.patch("mongobar.utils.os.path.exists", return_value=True) 703 | @mock.patch("mongobar.mongobar.get_directories", return_value=["d1", "d2"]) 704 | def test__get_backups(self, *args): 705 | m = mongobar.Mongobar() 706 | m.get_backups() 707 | args[0].assert_called_with(m.config.connection_dir) 708 | 709 | @mock.patch("mongobar.utils.os.path.exists", return_value=False) 710 | @mock.patch("mongobar.mongobar.create_directory") 711 | @mock.patch("mongobar.mongobar.get_directories", return_value=["d1", "d2"]) 712 | def test__get_backups__directory_does_not_exist__return_empty_list(self, *args): 713 | m = mongobar.Mongobar() 714 | self.assertEqual(m.get_backups(), []) 715 | 716 | # remove backup 717 | 718 | @mock.patch("mongobar.mongobar.shutil.rmtree") 719 | @mock.patch("mongobar.mongobar.os.path.exists", return_value=True) 720 | def test__remove_backup(self, *args): 721 | m = mongobar.Mongobar() 722 | m.remove_backup("foo") 723 | backup_directory = m.config.connection_dir 724 | args[1].assert_called_with(os.path.join(backup_directory, "foo")) 725 | 726 | @mock.patch("mongobar.mongobar.os.path.exists", return_value=False) 727 | @mock.patch("mongobar.mongobar.shutil.rmtree") 728 | def test__remove_backup__raises_BackupNotFoundError(self, *args): 729 | m = mongobar.Mongobar() 730 | with self.assertRaises(mongobar.exceptions.BackupNotFoundError): 731 | m.remove_backup("foo") 732 | -------------------------------------------------------------------------------- /mongobar/scripts/mongobar: -------------------------------------------------------------------------------- 1 | #!/Users/CHR15/.pyenv/shims/python 2 | 3 | import io 4 | import os 5 | import sys 6 | import argparse 7 | import terminaltables 8 | import textwrap 9 | import dateutil.parser 10 | import colorama 11 | import pprint 12 | import subprocess 13 | import copy 14 | import logging 15 | import tempfile 16 | import json 17 | 18 | import mongobar 19 | import mongobar.exceptions 20 | import mongobar.__version__ 21 | 22 | 23 | class ColoredFormatter(logging.Formatter): 24 | 25 | colors = { 26 | "DEBUG": "CYAN", 27 | "INFO": "WHITE", 28 | "WARNING": "YELLOW", 29 | "ERROR": "RED", 30 | "CRITICAL": "RED" 31 | } 32 | 33 | def format(self, record): 34 | color = getattr(colorama.Fore, self.colors[record.levelname]) 35 | return color + super().format(record) + colorama.Style.RESET_ALL 36 | 37 | 38 | class MongobarScript(object): 39 | 40 | default_config_file = "~/.mongobar_config.json" 41 | default_session_file = "~/.mongobar_session.json" 42 | 43 | log_file_format = "[%(asctime)s][%(levelname)-8s] %(message)s" 44 | log_time_format = "%Y-%m-%d %H:%M:%S" 45 | log_stream_format = "[%(levelname)-8s] %(message)s" 46 | 47 | def __init__(self): 48 | 49 | # mongobar 50 | self.mb = mongobar.Mongobar() 51 | 52 | # parsers 53 | self.parser, subparsers = self.create_parser_main() 54 | 55 | self.create_parser_connection(subparsers) 56 | self.create_parser_backup(subparsers) 57 | self.create_parser_restore(subparsers) 58 | self.create_parser_remove(subparsers) 59 | self.create_parser_backups(subparsers) 60 | self.create_parser_dirs(subparsers) 61 | self.create_parser_meta(subparsers) 62 | self.create_parser_server(subparsers) 63 | self.create_parser_config(subparsers) 64 | 65 | # parse args 66 | self.args = self.parser.parse_args() 67 | 68 | # config 69 | self.mb.config.add_file(self.args.config or self.default_config_file) 70 | 71 | args = {} 72 | if self.args.root_directory is not None: 73 | args["root_directory"] = self.args.root_directory 74 | if self.args.log_level is not None: 75 | args["log_level"] = self.args.log_level 76 | if self.args.log_file is not None: 77 | args["log_file"] = self.args.log_file 78 | 79 | if args: 80 | self.mb.config.add(args) 81 | 82 | # logging 83 | self.logger = logging.getLogger("mongobar_script") 84 | 85 | # level 86 | self.logger.setLevel(self.mb.config.log_level) 87 | self.mb.logger.setLevel(self.mb.config.log_level) 88 | self.mb.config.logger.setLevel(self.mb.config.log_level) 89 | 90 | # stream handler 91 | stream_handler = logging.StreamHandler(sys.stdout) 92 | stream_handler.setLevel(self.mb.config.log_level) 93 | stream_handler.setFormatter(ColoredFormatter(self.log_stream_format)) 94 | 95 | self.logger.addHandler(stream_handler) 96 | self.mb.logger.addHandler(stream_handler) 97 | self.mb.config.logger.addHandler(stream_handler) 98 | 99 | # file handler 100 | if self.mb.config.log_file is not None: 101 | try: 102 | file_handler = logging.FileHandler(os.path.expanduser(self.mb.config.log_file)) 103 | file_handler.setFormatter(logging.formatter(self.log_file_format)) 104 | file_handler.setLevel(self.mb.config.log_level) 105 | 106 | self.logger.addHandler(file_handler) 107 | self.mb.logger.addHandler(file_handler) 108 | self.mb.config.logger.addHandler(file_handler) 109 | 110 | except Exception as e: 111 | self.logger.critical(e) 112 | self.parser.exit() 113 | 114 | # session 115 | session = self.read_session() 116 | if session is not None: 117 | self.mb.config.connection = session["connection"] 118 | 119 | def run(self): 120 | try: 121 | getattr(self, self.args.action.replace("-", "_"))() 122 | except mongobar.exceptions.BaseError as e: 123 | self.logger.critical(str(e)) 124 | self.parser.exit(1) 125 | 126 | # parsers 127 | 128 | def create_parser_main(self): 129 | 130 | description = "mongobar 🍫 {}\nMongoDB Backup and Restore manager" 131 | description = description.format(mongobar.__version__.__version__) 132 | parser = argparse.ArgumentParser("mongobar", 133 | description=description, 134 | formatter_class=argparse.RawTextHelpFormatter 135 | ) 136 | 137 | # version 138 | parser.add_argument("-v", "--version", 139 | action="version", 140 | version=mongobar.__version__.__version__, 141 | help="Show the version number" 142 | ) 143 | 144 | 145 | # configuration group 146 | configuration_group = parser.add_argument_group("configuration arguments") 147 | 148 | # root directory 149 | configuration_group.add_argument("--root", 150 | dest="root_directory", 151 | metavar="ROOT", 152 | help="The root directory" 153 | ) 154 | 155 | # configuration file 156 | configuration_group.add_argument("--config", 157 | help="Path to the configuration file" 158 | ) 159 | 160 | # logging group 161 | logging_group = parser.add_argument_group("logging arguments") 162 | 163 | # loglevel 164 | logging_group.add_argument("--loglevel", 165 | dest="log_level", 166 | metavar="LOGLEVEL", 167 | choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], 168 | help="The log level" 169 | ) 170 | 171 | # # quiet 172 | # parser.add_argument("--quiet", 173 | # dest="quiet", 174 | # action="store_true" 175 | # ) 176 | 177 | # logfile 178 | logging_group.add_argument("--logfile", 179 | dest="log_file", 180 | metavar="LOGFILE", 181 | help="Path to the log file" 182 | ) 183 | 184 | # subparsers 185 | subparsers = parser.add_subparsers( 186 | dest="action", 187 | metavar="ACTION", 188 | title="action argument" 189 | ) 190 | subparsers.required = True 191 | 192 | return parser, subparsers 193 | 194 | def create_parser_connection(self, parent_parser): 195 | parser = parent_parser.add_parser("connection", 196 | help="Get or set the current connection", 197 | description="Get or set the current connection" 198 | ) 199 | 200 | # connection 201 | parser.add_argument("name", 202 | help="Name to set as the current connection", 203 | nargs="?" 204 | ) 205 | 206 | return parser 207 | 208 | def create_parser_backup(self, parent_parser): 209 | parser = parent_parser.add_parser("backup", 210 | help="Create a new backup", 211 | description="Create a new backup" 212 | ) 213 | 214 | # message 215 | parser.add_argument("-m", 216 | dest="message", 217 | metavar="MESSAGE", 218 | nargs="?", 219 | default="", 220 | help="A message to save with the backup" 221 | ) 222 | 223 | # output group 224 | output_group = parser.add_argument_group( 225 | "output arguments" 226 | ) 227 | 228 | # force 229 | output_group.add_argument("-f", "--force", 230 | dest="force", 231 | action="store_true", 232 | help="Skip confirmation prompt" 233 | ) 234 | 235 | # target group 236 | target_group = parser.add_argument_group( 237 | "target arguments" 238 | ) 239 | 240 | # connection 241 | target_group.add_argument("-c", 242 | dest="connection", 243 | metavar="CONNECTION", 244 | help="The config connection to use" 245 | ) 246 | 247 | # database 248 | target_group.add_argument("-d", 249 | dest="databases", 250 | metavar="DATABASE", 251 | action="append", 252 | help="The database(s) to target" 253 | ) 254 | 255 | # collection 256 | target_group.add_argument("--col", 257 | dest="collections", 258 | metavar="COLLECTION", 259 | action="append", 260 | help="The collection(s) to target" 261 | ) 262 | 263 | # host 264 | target_group.add_argument("--host", 265 | dest="host", 266 | metavar="HOST", 267 | help="The host to target" 268 | ) 269 | 270 | # port 271 | target_group.add_argument("--port", 272 | dest="port", 273 | type=int, 274 | metavar="PORT", 275 | help="The port to target" 276 | ) 277 | 278 | # authentication group 279 | authentication_group = parser.add_argument_group( 280 | "authentication arguments" 281 | ) 282 | 283 | # username 284 | authentication_group.add_argument("--user", 285 | dest="username", 286 | metavar="USER", 287 | help="Authentication username" 288 | ) 289 | 290 | # password 291 | authentication_group.add_argument("--pass", 292 | dest="password", 293 | metavar="PASS", 294 | help="Authentication password" 295 | ) 296 | 297 | # authentication database 298 | authentication_group.add_argument("--authdb", 299 | dest="authdb", 300 | metavar="AUTHDB", 301 | help="Authentication database" 302 | ) 303 | 304 | return parser 305 | 306 | def create_parser_restore(self, parent_parser): 307 | parser = parent_parser.add_parser("restore", 308 | help="Restore from a backup", 309 | description="Restore from a backup" 310 | ) 311 | 312 | # output group 313 | output_group = parser.add_argument_group( 314 | "output arguments" 315 | ) 316 | 317 | # force 318 | output_group.add_argument("-f", "--force", 319 | dest="force", 320 | action="store_true", 321 | help="Skip confirmation prompt" 322 | ) 323 | 324 | # source target group 325 | source_target_group = parser.add_argument_group( 326 | "source target arguments" 327 | ) 328 | 329 | # connection 330 | source_target_group.add_argument("-c", 331 | dest="connection", 332 | metavar="CONN", 333 | help="The config connection to use" 334 | ) 335 | 336 | # source database 337 | source_target_group.add_argument("-d", 338 | dest="databases", 339 | metavar="DATABASE", 340 | action="append", 341 | help="The source database(s) to target" 342 | ) 343 | 344 | # source collection 345 | source_target_group.add_argument("--col", 346 | dest="collections", 347 | metavar="COLLECTION", 348 | action="append", 349 | help="The source collection(s) to target" 350 | ) 351 | 352 | # source host 353 | source_target_group.add_argument("--host", 354 | dest="host", 355 | metavar="HOST", 356 | help="The source host to target" 357 | ) 358 | 359 | # source port 360 | source_target_group.add_argument("--port", 361 | dest="port", 362 | type=int, 363 | metavar="PORT", 364 | help="The source port to target" 365 | ) 366 | 367 | # destination target group 368 | destination_target_group = parser.add_argument_group( 369 | "destination target arguments" 370 | ) 371 | 372 | # destination connection 373 | destination_target_group.add_argument("-dc", 374 | dest="destination_connection", 375 | metavar="DCONN", 376 | help="The destination config connection to use" 377 | ) 378 | 379 | # destination database 380 | destination_target_group.add_argument("-dd", 381 | dest="destination_databases", 382 | metavar="DDATABASE", 383 | action="append", 384 | help="The destination databasee to target" 385 | ) 386 | 387 | # destination host 388 | destination_target_group.add_argument("--dhost", 389 | dest="destination_host", 390 | metavar="DHOST", 391 | help="The destination host to target" 392 | ) 393 | 394 | # destiantion port 395 | destination_target_group.add_argument("--dport", 396 | dest="destination_port", 397 | metavar="DPORT", 398 | help="The destination port to target" 399 | ) 400 | 401 | # destination authentication group 402 | destination_authentication_group = parser.add_argument_group( 403 | "destination authentication arguments" 404 | ) 405 | 406 | # destination username 407 | destination_authentication_group.add_argument("--duser", 408 | dest="destination_username", 409 | metavar="DUSER", 410 | help="Destination authentication username" 411 | ) 412 | 413 | # destination password 414 | destination_authentication_group.add_argument("--dpass", 415 | dest="destination_password", 416 | metavar="DPASS", 417 | help="Destination authentication password" 418 | ) 419 | 420 | # destination authdb 421 | destination_authentication_group.add_argument("--dauthdb", 422 | dest="destination_authdb", 423 | metavar="DAUTHDB", 424 | help="Destination authentication database" 425 | ) 426 | 427 | # backup 428 | parser.add_argument("backup") 429 | 430 | return parser 431 | 432 | def create_parser_remove(self, parent_parser): 433 | parser = parent_parser.add_parser("remove", 434 | help="Remove a backup", 435 | description="Remove a backup" 436 | ) 437 | 438 | # output group 439 | output_group = parser.add_argument_group( 440 | "output arguments" 441 | ) 442 | 443 | # force 444 | output_group.add_argument("-f", "--force", 445 | dest="force", 446 | action="store_true", 447 | help="Skip confirmation prompt" 448 | ) 449 | 450 | # target group 451 | target_group = parser.add_argument_group( 452 | "target arguments" 453 | ) 454 | 455 | # connection 456 | target_group.add_argument("-c", 457 | dest="connection", 458 | metavar="CONNECTION", 459 | help="The config connection to use" 460 | ) 461 | 462 | # source host 463 | target_group.add_argument("--host", 464 | dest="host", 465 | metavar="HOST", 466 | help="The host to target" 467 | ) 468 | 469 | # source port 470 | target_group.add_argument("--port", 471 | dest="port", 472 | type=int, 473 | metavar="PORT", 474 | help="The port to target" 475 | ) 476 | 477 | # backup 478 | parser.add_argument("backup", 479 | help="The backup to remove" 480 | ) 481 | 482 | return parser 483 | 484 | def create_parser_backups(self, parent_parser): 485 | parser = parent_parser.add_parser("backups", 486 | help="List backups", 487 | description="List backups" 488 | ) 489 | 490 | # output group 491 | output_group = parser.add_argument_group( 492 | "output arguments" 493 | ) 494 | 495 | # limit 496 | output_group.add_argument("-l", 497 | type=int, 498 | dest="limit", 499 | metavar="LIMIT", 500 | help="Limit output to LIMIT rows" 501 | ) 502 | 503 | # target group 504 | target_group = parser.add_argument_group( 505 | "target arguments" 506 | ) 507 | 508 | # connection 509 | target_group.add_argument("-c", 510 | dest="connection", 511 | metavar="CONNECTION", 512 | help="The config connection to use" 513 | ) 514 | 515 | # source host 516 | target_group.add_argument("--host", 517 | dest="host", 518 | metavar="HOST", 519 | help="The host to target" 520 | ) 521 | 522 | # source port 523 | target_group.add_argument("--port", 524 | dest="port", 525 | type=int, 526 | metavar="PORT", 527 | help="The port to target" 528 | ) 529 | 530 | return parser 531 | 532 | def create_parser_dirs(self, parent_parser): 533 | parser = parent_parser.add_parser("dirs", 534 | help="List connection directories", 535 | description="List connection directories" 536 | ) 537 | 538 | # output group 539 | output_group = parser.add_argument_group( 540 | "output arguments" 541 | ) 542 | 543 | # limit 544 | output_group.add_argument("-l", 545 | type=int, 546 | dest="limit", 547 | metavar="LIMIT", 548 | help="Limit output to LIMIT rows" 549 | ) 550 | 551 | return parser 552 | 553 | def create_parser_meta(self, parent_parser): 554 | parser = parent_parser.add_parser("meta", 555 | help="View metadata for backup", 556 | description="View metadata for backup" 557 | ) 558 | 559 | # source backup 560 | parser.add_argument("backup", 561 | help="The backup to view metadata for" 562 | ) 563 | 564 | # target group 565 | target_group = parser.add_argument_group( 566 | "target arguments" 567 | ) 568 | 569 | # connection 570 | target_group.add_argument("-c", 571 | dest="connection", 572 | metavar="CONNECTION", 573 | help="The config connection to use" 574 | ) 575 | 576 | # host 577 | target_group.add_argument("--host", 578 | dest="host", 579 | metavar="HOST", 580 | help="The host to target" 581 | ) 582 | 583 | # port 584 | target_group.add_argument("--port", 585 | dest="port", 586 | type=int, 587 | metavar="PORT", 588 | help="The port to target" 589 | ) 590 | 591 | return parser 592 | 593 | def create_parser_server(self, parent_parser): 594 | parser = parent_parser.add_parser("server", 595 | help="View metadata for server", 596 | description="View metadata for server" 597 | ) 598 | 599 | # target group 600 | target_group = parser.add_argument_group( 601 | "target arguments" 602 | ) 603 | 604 | # connection 605 | target_group.add_argument("-c", 606 | dest="connection", 607 | metavar="CONNECTION", 608 | help="The config connection to use" 609 | ) 610 | 611 | # source host 612 | target_group.add_argument("--host", 613 | dest="host", 614 | metavar="HOST", 615 | help="The host to target" 616 | ) 617 | 618 | # source port 619 | target_group.add_argument("--port", 620 | dest="port", 621 | type=int, 622 | metavar="PORT", 623 | help="The port to target" 624 | ) 625 | 626 | # authentication group 627 | authentication_group = parser.add_argument_group( 628 | "authentication arguments" 629 | ) 630 | 631 | # username 632 | authentication_group.add_argument("--user", 633 | dest="username", 634 | metavar="USER", 635 | help="Authentication username" 636 | ) 637 | 638 | # password 639 | authentication_group.add_argument("--pass", 640 | dest="password", 641 | metavar="PASS", 642 | help="Authentication password" 643 | ) 644 | 645 | # authentication database 646 | authentication_group.add_argument("--authdb", 647 | dest="authdb", 648 | metavar="AUTHDB", 649 | help="Authentication database" 650 | ) 651 | 652 | return parser 653 | 654 | def create_parser_config(self, parent_parser): 655 | parser = parent_parser.add_parser("config", 656 | help="View configuration data", 657 | description="View configuration data" 658 | ) 659 | 660 | # input 661 | 662 | def capture_bool_input(self): 663 | if input("Are you sure you want to continue? [y/n]: ")[:1].lower() != "y": 664 | self.parser.exit() 665 | 666 | return True 667 | 668 | def capture_multiline_input(self): 669 | 670 | try: 671 | 672 | with tempfile.NamedTemporaryFile() as file_handle: 673 | subprocess.call([os.environ.get("EDITOR", "nano"), file_handle.name]) 674 | multiline = file_handle.read() 675 | mutliline = multiline.decode("utf-8").rstrip("\n") 676 | return multiline 677 | 678 | except Exception as e: 679 | self.logger.critical("Unable to open EDITOR: {}".format(e)) 680 | self.parser.exit() 681 | 682 | # session 683 | 684 | def read_session(self): 685 | session_file = os.path.expanduser(self.default_session_file) 686 | 687 | try: 688 | with open(session_file) as file_handle: 689 | data = json.loads(file_handle.read()) 690 | self.logger.debug("Session file successfully read: {}".format(self.default_session_file)) 691 | self.logger.debug("Data: {}".format(pprint.pformat(data))) 692 | 693 | except (FileNotFoundError, PermissionError) as e: 694 | self.logger.debug(e) 695 | return None 696 | 697 | return data 698 | 699 | def write_session(self, data): 700 | session_file = os.path.expanduser(self.default_session_file) 701 | 702 | try: 703 | with open(session_file, "w+") as file_handle: 704 | file_handle.write(json.dumps(data)) 705 | self.logger.debug("Session file successfully written: {}".format(self.default_session_file)) 706 | self.logger.debug("Data: {}".format(pprint.pformat(data))) 707 | 708 | except (FileNotFoundError, PermissionError) as e: 709 | self.logger.error(e) 710 | return None 711 | 712 | return data 713 | 714 | # format tables 715 | 716 | def format_metadata_title_table(self, name, metadata): 717 | 718 | data = [["Name", "Date & Time"]] 719 | 720 | data.append([ 721 | self.format_backup_name(name), 722 | self.format_date(metadata["date"]) 723 | ]) 724 | 725 | table = terminaltables.SingleTable(data) 726 | 727 | return table.table 728 | 729 | def format_metadata_metrics_table(self, metadata, databases=None, collections=None, title=None): 730 | 731 | data = [["Databases", "Collections", "Documents"]] 732 | 733 | for i, database in enumerate(metadata["databases"]): 734 | if not databases or database["name"] in databases: 735 | for j, collection in enumerate(database["collections"]): 736 | if not collections or collection["name"] in collections: 737 | data.append([ 738 | database["name"] if j == 0 else "", 739 | collection["name"], 740 | collection["document_count"] 741 | ]) 742 | 743 | table = terminaltables.SingleTable(data, title) 744 | 745 | table.justify_columns[2] = "right" 746 | 747 | return table.table 748 | 749 | def format_metadata_message_table(self, message=None): 750 | 751 | data = [["Message"], [self.format_metadata_message(message)]] 752 | 753 | table = terminaltables.SingleTable(data) 754 | 755 | return table.table 756 | 757 | def format_connection_table(self): 758 | 759 | data = [ 760 | ["Name", "Host", "Port", "Auth"], 761 | [ 762 | self.args.connection, 763 | self.mb.get_connection()["host"], 764 | self.mb.get_connection()["port"], 765 | "Disabled" 766 | ] 767 | ] 768 | 769 | table = terminaltables.SingleTable(data, " Current Connection ") 770 | 771 | return table.table 772 | 773 | def format_metadata_message(self, message=None, width=None, first_line=False): 774 | if message is None: 775 | return "" 776 | 777 | if width is None: 778 | width = 100 779 | 780 | lines = message.split("\n") 781 | lines = [ textwrap.wrap(line, width) for line in lines ] 782 | 783 | if first_line: 784 | return lines[0][0] 785 | else: 786 | return "\n".join([ "\n".join(line) for line in lines ]) 787 | 788 | # format strings 789 | 790 | def format_backup_name(self, name): 791 | name = colorama.Fore.CYAN + name + colorama.Style.RESET_ALL 792 | return name 793 | 794 | def format_connection_name(self, name): 795 | name = "[{}]".format(name) 796 | name = colorama.Fore.YELLOW + name + colorama.Style.RESET_ALL 797 | return name 798 | 799 | def color_warning(self, string): 800 | return colorama.Fore.YELLOW + string + colorama.Style.RESET_ALL 801 | 802 | def color_success(self, string): 803 | return colorama.Fore.CYAN + string + colorama.Style.RESET_ALL 804 | 805 | def color_error(self, string): 806 | return colorama.Fore.RED + string + colorama.Style.RESET_ALL 807 | 808 | def format_date(self, datetime_string): 809 | return dateutil.parser.parse(datetime_string).strftime("%m/%d/%Y %I:%M %p") 810 | 811 | # actions 812 | 813 | def connection(self): 814 | 815 | if self.args.name is None: 816 | msg = "Current connection: {}" 817 | connection_name = self.format_connection_name(self.mb.config.connection.name) 818 | print(msg.format(connection_name)) 819 | 820 | else: 821 | connections = [ k for k in self.mb.config.config["connections"].keys() ] 822 | 823 | if self.args.name not in connections: 824 | self.logger.error(self.color_error("Connection not set in config: '{}'".format(self.args.name))) 825 | 826 | else: 827 | self.write_session({"connection": self.args.name}) 828 | msg = "Current connection: {}" 829 | connection_name = self.format_connection_name(self.args.name) 830 | print(msg.format(connection_name)) 831 | 832 | def backup(self): 833 | 834 | # handle script args 835 | 836 | if self.args.connection is not None: 837 | self.mb.config.connection = self.args.connection 838 | 839 | data = {} 840 | if self.args.host is not None: 841 | data["host"] = self.args.host 842 | if self.args.port is not None: 843 | data["port"] = self.args.port 844 | if self.args.username is not None: 845 | data["username"] = self.args.username 846 | if self.args.password is not None: 847 | data["password"] = self.args.password 848 | if self.args.authdb is not None: 849 | data["authdb"] = self.args.authdb 850 | 851 | self.mb.config.add({ 852 | "connections": { 853 | self.mb.config.connection.name: data 854 | } 855 | }) 856 | 857 | # backup 858 | 859 | if self.args.message is None: 860 | self.args.message = self.capture_multiline_input() 861 | print(self.args.message, type(self.args.message)) 862 | 863 | if not self.args.force: 864 | 865 | metadata = self.mb.generate_metadata() 866 | table = self.format_metadata_metrics_table( 867 | metadata, 868 | self.args.databases, 869 | self.args.collections, 870 | ) 871 | 872 | print() 873 | print(self.color_warning("About to create a new backup of the following data:")) 874 | print() 875 | print(table) 876 | 877 | if self.args.message: 878 | message_table = self.format_metadata_message_table(self.args.message) 879 | print(message_table) 880 | 881 | print() 882 | self.capture_bool_input() 883 | print() 884 | 885 | backup_name = self.mb.backup( 886 | databases=self.args.databases or None, 887 | collections=self.args.collections or None, 888 | message=self.args.message or None 889 | ) 890 | 891 | print(self.color_success("Backup {} created!".format(backup_name))) 892 | print() 893 | 894 | def restore(self): 895 | 896 | # handle script args 897 | 898 | # source connection 899 | 900 | if self.args.connection: 901 | self.mb.connection = self.args.connection 902 | 903 | data = {} 904 | if self.args.host is not None: 905 | data["host"] = self.args.host 906 | if self.args.port is not None: 907 | data["port"] = self.args.port 908 | 909 | self.mb.config.add({ 910 | "connections": { 911 | self.mb.config.connection.name: data 912 | } 913 | }) 914 | 915 | # destination connection 916 | # TODO: this is a mess because of only being able to get a connection 917 | # as a class and not a dict, a dict would allow for reshaping and 918 | # reinserting the data without jumping through so many h00ps 919 | 920 | if self.args.destination_connection is not None: 921 | destconn_name = self.args.destination_connection 922 | destconn = self.mb.config.connections.get(destconn_name).get() 923 | 924 | else: 925 | destconn_name = "%%destination_connection%%" 926 | destconn = {} 927 | 928 | if self.args.destination_host is not None: 929 | destconn["host"] = self.args.destination_host 930 | elif "host" not in destconn: 931 | destconn["host"] = self.mb.config.connection.host 932 | 933 | if self.args.destination_port is not None: 934 | destconn["port"] = self.args.destination_port 935 | elif "port" not in destconn: 936 | destconn["port"] = self.mb.config.connection.port 937 | 938 | if self.args.destination_username is not None: 939 | destconn["username"] = self.args.destination_username 940 | elif "username" not in destconn: 941 | destconn["username"] = self.mb.config.connection.username 942 | 943 | if self.args.destination_password is not None: 944 | destconn["password"] = self.args.destination_password 945 | elif "password" not in destconn: 946 | destconn["password"] = self.mb.config.connection.password 947 | 948 | if self.args.destination_authdb is not None: 949 | destconn["authdb"] = self.args.destination_authdb 950 | elif "authdb" not in destconn: 951 | destconn["authdb"] = self.mb.config.connection.authdb 952 | 953 | self.mb.config.add({ 954 | "connections": { 955 | destconn_name: destconn 956 | } 957 | }) 958 | 959 | # restore ~~~ 960 | 961 | metadata = self.mb.read_metadata(self.args.backup) 962 | 963 | if not self.args.force: 964 | 965 | print() 966 | print(self.color_warning("About to restore the following backups:")) 967 | print() 968 | print(self.format_metadata_title_table(self.args.backup, metadata)) 969 | print(self.format_metadata_metrics_table(metadata, self.args.databases, self.args.collections)) 970 | print() 971 | print(self.color_warning("To the following target:")) 972 | print() 973 | 974 | data = [["Host", "Port"]] 975 | connection = self.mb.config.connections.get(destconn_name) 976 | if not self.args.destination_databases: 977 | data.append([connection.host, connection.port]) 978 | 979 | else: 980 | data[0].append("Databases") 981 | for i, db in enumerate(self.args.destination_databases): 982 | data.append([ 983 | connection.host if i == 0 else "", 984 | connection.port if i == 0 else "", 985 | db 986 | ]) 987 | 988 | print(terminaltables.SingleTable(data).table) 989 | print() 990 | 991 | self.capture_bool_input() 992 | 993 | self.mb.restore( 994 | name=self.args.backup, 995 | databases=self.args.databases or None, 996 | collections=self.args.collections or None, 997 | destination_databases=self.args.destination_databases or None, 998 | destination_connection=destconn_name 999 | ) 1000 | 1001 | print(self.color_success("Backup '{}' restored!".format(self.args.backup))) 1002 | 1003 | def remove(self): 1004 | 1005 | if self.args.connection: 1006 | self.mb.connection = self.args.connection 1007 | 1008 | data = {} 1009 | if self.args.host is not None: 1010 | data["host"] = self.args.host 1011 | if self.args.port is not None: 1012 | data["port"] = self.args.port 1013 | 1014 | self.mb.config.add({ 1015 | "connections": { 1016 | self.mb.config.connection.name: data 1017 | } 1018 | }) 1019 | 1020 | # ~~~ 1021 | 1022 | backup_name = self.args.backup 1023 | 1024 | backup_path = os.path.join( 1025 | self.mb.config.connection_dir, 1026 | self.args.backup 1027 | ) 1028 | 1029 | # check if backup directory exists 1030 | if not os.path.exists(backup_path): 1031 | msg = "Backup '{}' not found in connection directory '{}'".format( 1032 | backup_name, 1033 | self.mb.config.connection_dir 1034 | ) 1035 | self.logger.critical(msg) 1036 | self.parser.exit() 1037 | 1038 | if not self.args.force: 1039 | print() 1040 | print("About to remove backup {}.".format(backup_name)) 1041 | print() 1042 | self.capture_bool_input() 1043 | print() 1044 | 1045 | self.mb.remove_backup(self.args.backup) 1046 | print("Backup {} removed!".format(backup_name)) 1047 | print() 1048 | 1049 | def meta(self): 1050 | 1051 | if self.args.connection: 1052 | self.mb.connection = self.args.connection 1053 | 1054 | data = {} 1055 | if self.args.host is not None: 1056 | data["host"] = self.args.host 1057 | if self.args.port is not None: 1058 | data["port"] = self.args.port 1059 | 1060 | self.mb.config.add({ 1061 | "connections": { 1062 | self.mb.config.connection.name: data 1063 | } 1064 | }) 1065 | 1066 | # ~~~ 1067 | 1068 | metadata = self.mb.read_metadata(self.args.backup) 1069 | 1070 | print() 1071 | print(self.format_metadata_title_table(self.args.backup, metadata)) 1072 | print(self.format_metadata_metrics_table(metadata)) 1073 | 1074 | if metadata["message"]: 1075 | print(self.format_metadata_message_table(metadata["message"])) 1076 | 1077 | print() 1078 | 1079 | def server(self): 1080 | 1081 | if self.args.connection: 1082 | self.mb.connection = self.args.connection 1083 | 1084 | data = {} 1085 | if self.args.host is not None: 1086 | data["host"] = self.args.host 1087 | if self.args.port is not None: 1088 | data["port"] = self.args.port 1089 | if self.args.username is not None: 1090 | data["username"] = self.args.username 1091 | if self.args.password is not None: 1092 | data["password"] = self.args.password 1093 | if self.args.authdb is not None: 1094 | data["authdb"] = self.args.authdb 1095 | 1096 | self.mb.config.add({ 1097 | "connections": { 1098 | self.mb.config.connection.name: data 1099 | } 1100 | }) 1101 | 1102 | # ~~~ 1103 | 1104 | metadata = self.mb.generate_metadata() 1105 | 1106 | connection_name = self.format_connection_name(self.mb.config.connection.name) 1107 | title = " Server {} ".format(connection_name) 1108 | 1109 | print() 1110 | print(self.format_metadata_metrics_table(metadata, title=title)) 1111 | print() 1112 | 1113 | def backups(self): 1114 | 1115 | if self.args.connection: 1116 | self.mb.config.connection = self.args.connection 1117 | 1118 | data = {} 1119 | if self.args.host is not None: 1120 | data["host"] = self.args.host 1121 | if self.args.port is not None: 1122 | data["port"] = self.args.port 1123 | 1124 | self.mb.config.add({ 1125 | "connections": { 1126 | self.mb.config.connection.name: data 1127 | } 1128 | }) 1129 | 1130 | # ~~~ 1131 | 1132 | backups_list = self.mb.get_backups() 1133 | 1134 | if len(backups_list) == 0: 1135 | table_data = [["No backups have been created"]] 1136 | print() 1137 | print(terminaltables.SingleTable(table_data).table) 1138 | print() 1139 | 1140 | else: 1141 | table_data = [["Name", "Date & Time", "DB", "C", "D", "Message"]] 1142 | 1143 | backups = [] 1144 | for backup in backups_list: 1145 | 1146 | # read metadata 1147 | metadata = self.mb.read_metadata(backup) 1148 | backups.append(metadata) 1149 | 1150 | # inject name 1151 | metadata["name"] = self.format_backup_name(backup) 1152 | 1153 | # database count 1154 | metadata["databases_count"] = len(metadata["databases"]) 1155 | 1156 | # collection count 1157 | collection_count = 0 1158 | for database in metadata["databases"]: 1159 | collection_count += len(database["collections"]) 1160 | metadata["collections_count"] = collection_count 1161 | 1162 | # document count 1163 | document_count = 0 1164 | for database in metadata["databases"]: 1165 | for collection in database["collections"]: 1166 | document_count += collection["document_count"] 1167 | metadata["documents_count"] = document_count 1168 | 1169 | # sort backups by date 1170 | backups.sort(key=lambda x: x["date"], reverse=True) 1171 | 1172 | for i, backup in enumerate(backups): 1173 | 1174 | # limit 1175 | if self.args.limit and i == self.args.limit: 1176 | break 1177 | 1178 | table_data.append([ 1179 | backup["name"], 1180 | self.format_date(backup["date"]), 1181 | backup["databases_count"], 1182 | backup["collections_count"], 1183 | backup["documents_count"], 1184 | self.format_metadata_message(backup["message"], 32, True) 1185 | ]) 1186 | 1187 | connection_name = self.format_connection_name(self.mb.config.connection.name) 1188 | title = " Backups {} ".format(connection_name) 1189 | 1190 | table = terminaltables.SingleTable(table_data, title=title) 1191 | 1192 | table.justify_columns[2] = "right" 1193 | table.justify_columns[3] = "right" 1194 | table.justify_columns[4] = "right" 1195 | 1196 | print() 1197 | print(table.table) 1198 | print() 1199 | 1200 | def dirs(self): 1201 | 1202 | dirs = self.mb.get_connection_directories(count=True) 1203 | 1204 | print() 1205 | 1206 | if len(dirs) == 0: 1207 | data = [["No connection directories have been created"]] 1208 | table = terminaltables.SingleTable(data) 1209 | print(table.table) 1210 | print() 1211 | 1212 | else: 1213 | data = [("Name", "Connection", "Backups")] 1214 | for dir_ in dirs: 1215 | 1216 | name = self.mb.config.connections.get(socket=dir_[0]).name or "" 1217 | name = self.format_connection_name(name) 1218 | row = [dir_[0], name, dir_[1]] 1219 | 1220 | # limit 1221 | if self.args.limit and i == self.args.limit: 1222 | break 1223 | 1224 | data.append(row) 1225 | 1226 | table = terminaltables.SingleTable(data, " Connection Directories ") 1227 | table.justify_columns[2] = "right" 1228 | 1229 | print(table.table) 1230 | print() 1231 | 1232 | def config(self): 1233 | 1234 | rows = [] 1235 | for key, val in self.mb.config.config.items(): 1236 | if key != "connections": 1237 | rows.append([key, val]) 1238 | 1239 | table = terminaltables.SingleTable(rows) 1240 | table.inner_heading_row_border = False 1241 | 1242 | print() 1243 | print(table.table) 1244 | print() 1245 | print("Connections:") 1246 | print() 1247 | 1248 | for name, host in self.mb.config.config["connections"].items(): 1249 | rows = [] 1250 | for key, val in host.items(): 1251 | rows.append([key.ljust(9), val]) 1252 | 1253 | title = " {} ".format(self.format_connection_name(name)) 1254 | table = terminaltables.SingleTable(rows, title) 1255 | table.inner_heading_row_border = False 1256 | print(table.table) 1257 | 1258 | print() 1259 | 1260 | 1261 | MongobarScript().run() 1262 | -------------------------------------------------------------------------------- /mongobar/data/verbs.txt: -------------------------------------------------------------------------------- 1 | abandon 2 | abase 3 | abash 4 | abate 5 | abbreviate 6 | abdicate 7 | abduct 8 | abet 9 | abhor 10 | abide 11 | abjure 12 | ablate 13 | abnegate 14 | abolish 15 | abominate 16 | abort 17 | abound 18 | abrade 19 | abridge 20 | abrogate 21 | abscess 22 | abscond 23 | abseil 24 | absent 25 | absolve 26 | absorb 27 | abstain 28 | abstract 29 | abuse 30 | abut 31 | accede 32 | accelerate 33 | accent 34 | accentuate 35 | accept 36 | access 37 | acclaim 38 | acclimate 39 | acclimatize 40 | accommodate 41 | accompany 42 | accomplish 43 | accord 44 | accost 45 | account 46 | accouter 47 | accoutre 48 | accredit 49 | accrue 50 | acculturate 51 | accumulate 52 | accuse 53 | accustom 54 | ace 55 | acerbate 56 | ache 57 | achieve 58 | acidify 59 | acknowledge 60 | acquaint 61 | acquiesce 62 | acquire 63 | acquit 64 | act 65 | activate 66 | actualize 67 | actuate 68 | acupuncture 69 | adapt 70 | add 71 | addict 72 | addle 73 | address 74 | adduce 75 | adhere 76 | adjoin 77 | adjourn 78 | adjudge 79 | adjudicate 80 | adjure 81 | adjust 82 | administer 83 | administrate 84 | admire 85 | admit 86 | admix 87 | admonish 88 | adopt 89 | adore 90 | adorn 91 | adsorb 92 | adulate 93 | adulterate 94 | adumbrate 95 | advance 96 | advantage 97 | adventure 98 | advert 99 | advertise 100 | advertize 101 | advise 102 | advocate 103 | adz 104 | adze 105 | aerate 106 | affect 107 | affiance 108 | affiliate 109 | affirm 110 | affix 111 | afflict 112 | afford 113 | afforest 114 | affray 115 | affront 116 | age 117 | agent 118 | agglomerate 119 | agglutinate 120 | aggrandize 121 | aggravate 122 | aggregate 123 | aggrieve 124 | agitate 125 | agonize 126 | agree 127 | aid 128 | ail 129 | aim 130 | air 131 | airbrush 132 | airdrop 133 | airfreight 134 | airlift 135 | airmail 136 | alarm 137 | alert 138 | alias 139 | alibi 140 | alienate 141 | alight 142 | align 143 | aliment 144 | aline 145 | alkalize 146 | allay 147 | allege 148 | alleviate 149 | alligator 150 | alliterate 151 | allocate 152 | allot 153 | allow 154 | allowance 155 | alloy 156 | allude 157 | allure 158 | ally 159 | alphabetize 160 | alter 161 | alternate 162 | amalgamate 163 | amass 164 | amaze 165 | ambition 166 | amble 167 | ambulate 168 | ambuscade 169 | ambush 170 | ameliorate 171 | amend 172 | amerce 173 | amnesty 174 | amortize 175 | amount 176 | amplify 177 | amputate 178 | amuse 179 | anaesthetize 180 | anagram 181 | analogize 182 | analyse 183 | analyze 184 | anathematize 185 | anatomize 186 | anchor 187 | anesthetize 188 | angel 189 | anger 190 | angle 191 | anglicize 192 | anguish 193 | animadvert 194 | animate 195 | anneal 196 | annex 197 | annihilate 198 | annotate 199 | announce 200 | annoy 201 | annul 202 | anodize 203 | anoint 204 | answer 205 | antagonize 206 | ante 207 | antedate 208 | anthem 209 | anthologize 210 | anticipate 211 | antidote 212 | antiquate 213 | antique 214 | ape 215 | apologize 216 | apostatize 217 | appal 218 | appall 219 | apparel 220 | appeal 221 | appear 222 | appease 223 | append 224 | appertain 225 | applaud 226 | applique 227 | apply 228 | appoint 229 | apportion 230 | appose 231 | appraise 232 | appreciate 233 | apprehend 234 | apprentice 235 | apprise 236 | apprize 237 | approach 238 | appropriate 239 | approve 240 | approximate 241 | apron 242 | aquaplane 243 | arbitrage 244 | arbitrate 245 | arc 246 | arcade 247 | arch 248 | architect 249 | archive 250 | argue 251 | arise 252 | arm 253 | armor 254 | armour 255 | arouse 256 | arraign 257 | arrange 258 | array 259 | arrest 260 | arrive 261 | arrogate 262 | arrow 263 | art 264 | article 265 | articulate 266 | ascend 267 | ascertain 268 | ascribe 269 | ashlar 270 | ask 271 | asphalt 272 | asphyxiate 273 | aspirate 274 | aspire 275 | assail 276 | assassinate 277 | assault 278 | assay 279 | assemble 280 | assent 281 | assert 282 | assess 283 | asseverate 284 | assign 285 | assimilate 286 | assist 287 | associate 288 | assort 289 | assuage 290 | assume 291 | assure 292 | asterisk 293 | astonish 294 | astound 295 | atomize 296 | atone 297 | atrophy 298 | attach 299 | attack 300 | attain 301 | attempt 302 | attend 303 | attenuate 304 | attest 305 | attire 306 | attitudinize 307 | attract 308 | attribute 309 | attune 310 | auction 311 | auctioneer 312 | audit 313 | audition 314 | augment 315 | augur 316 | auscultate 317 | authenticate 318 | author 319 | authorize 320 | autoclave 321 | autograph 322 | automate 323 | automatize 324 | autopsy 325 | avail 326 | avalanche 327 | avenge 328 | aver 329 | average 330 | avert 331 | avoid 332 | avouch 333 | avow 334 | await 335 | awake 336 | awaken 337 | award 338 | awe 339 | ax 340 | axe 341 | baa 342 | babble 343 | baby 344 | babysit 345 | back 346 | backbite 347 | backdate 348 | backdrop 349 | backfire 350 | backgammon 351 | background 352 | backhand 353 | backlash 354 | backlog 355 | backpack 356 | backpedal 357 | backslide 358 | backspace 359 | backstop 360 | backstroke 361 | backtrack 362 | backwash 363 | badge 364 | badger 365 | badinage 366 | badmouth 367 | baffle 368 | bag 369 | bagpipe 370 | bail 371 | bait 372 | baize 373 | bake 374 | baksheesh 375 | balance 376 | bald 377 | bale 378 | balk 379 | ball 380 | ballast 381 | balloon 382 | ballot 383 | ballyhoo 384 | bamboozle 385 | ban 386 | band 387 | bandage 388 | bandy 389 | bang 390 | banish 391 | bank 392 | bankroll 393 | bankrupt 394 | banquet 395 | banter 396 | baptize 397 | bar 398 | barb 399 | barbarize 400 | barbecue 401 | barbeque 402 | barber 403 | bard 404 | bare 405 | barf 406 | bargain 407 | barge 408 | barhop 409 | bark 410 | barn 411 | barnstorm 412 | barrack 413 | barrage 414 | barrel 415 | barricade 416 | barter 417 | base 418 | bash 419 | bask 420 | basset 421 | bastardize 422 | baste 423 | bat 424 | batch 425 | bate 426 | bath 427 | bathe 428 | batik 429 | batten 430 | batter 431 | battle 432 | battledore 433 | baulk 434 | bawl 435 | bay 436 | bayonet 437 | be 438 | beach 439 | beacon 440 | bead 441 | beam 442 | bean 443 | bear 444 | beard 445 | beat 446 | beatify 447 | beau 448 | beautify 449 | beaver 450 | becalm 451 | beck 452 | beckon 453 | becloud 454 | become 455 | bed 456 | bedaub 457 | bedazzle 458 | bedeck 459 | bedevil 460 | bedim 461 | bedizen 462 | bedraggle 463 | beef 464 | beep 465 | beeswax 466 | beetle 467 | befall 468 | befit 469 | befog 470 | befoul 471 | befriend 472 | befuddle 473 | beg 474 | beget 475 | beggar 476 | begin 477 | begone 478 | begrime 479 | begrudge 480 | beguile 481 | begum 482 | behave 483 | behead 484 | behold 485 | behoove 486 | bejewel 487 | belabor 488 | belabour 489 | belay 490 | belch 491 | beleaguer 492 | belie 493 | believe 494 | belittle 495 | bell 496 | bellow 497 | belly 498 | bellyache 499 | belong 500 | belt 501 | bemire 502 | bemoan 503 | bemuse 504 | bench 505 | benchmark 506 | bend 507 | benefice 508 | benefit 509 | benumb 510 | bequeath 511 | berate 512 | bereave 513 | berry 514 | berth 515 | beseech 516 | beseem 517 | beset 518 | besiege 519 | besmear 520 | besmirch 521 | besot 522 | bespangle 523 | bespatter 524 | bespeak 525 | best 526 | bestir 527 | bestow 528 | bestrew 529 | bestride 530 | bet 531 | betake 532 | bethink 533 | betide 534 | betoken 535 | betray 536 | betroth 537 | better 538 | bevel 539 | bewail 540 | beware 541 | bewilder 542 | bewitch 543 | bias 544 | bib 545 | bicker 546 | bicycle 547 | bide 548 | bifurcate 549 | big 550 | bight 551 | bike 552 | bilge 553 | bilk 554 | bill 555 | billboard 556 | billet 557 | billow 558 | bin 559 | bind 560 | binge 561 | biodegrade 562 | biopsy 563 | birch 564 | bird 565 | birdie 566 | birdlime 567 | birth 568 | bisect 569 | bishop 570 | bit 571 | bitch 572 | bite 573 | bitter 574 | bivouac 575 | blab 576 | blabber 577 | black 578 | blackball 579 | blackbird 580 | blacken 581 | blackguard 582 | blackjack 583 | blacklist 584 | blackmail 585 | blacktop 586 | blame 587 | blanch 588 | blandish 589 | blank 590 | blanket 591 | blare 592 | blarney 593 | blaspheme 594 | blast 595 | blather 596 | blaze 597 | blazon 598 | bleach 599 | blear 600 | bleat 601 | bleed 602 | bleep 603 | blemish 604 | blench 605 | blend 606 | bless 607 | blight 608 | blind 609 | blindfold 610 | blindside 611 | blink 612 | blinker 613 | blip 614 | blister 615 | blitz 616 | blitzkrieg 617 | bloat 618 | blob 619 | block 620 | blockade 621 | blood 622 | bloody 623 | bloom 624 | bloop 625 | blossom 626 | blot 627 | blotch 628 | blouse 629 | blow 630 | blowtorch 631 | blubber 632 | bludgeon 633 | blue 634 | blueprint 635 | bluff 636 | blunder 637 | blunt 638 | blur 639 | blurb 640 | blurt 641 | blush 642 | bluster 643 | board 644 | boast 645 | boat 646 | bob 647 | bobble 648 | bobsled 649 | bobsleigh 650 | bobtail 651 | bode 652 | body 653 | bog 654 | bogey 655 | boggle 656 | bogie 657 | boil 658 | boldface 659 | bollix 660 | bolster 661 | bolt 662 | bomb 663 | bombard 664 | bombproof 665 | bond 666 | bone 667 | bong 668 | bonnet 669 | boo 670 | boob 671 | boodle 672 | boogie 673 | boohoo 674 | book 675 | bookend 676 | bookmark 677 | boom 678 | boomerang 679 | boondoggle 680 | boost 681 | boot 682 | bootleg 683 | bootstrap 684 | booze 685 | bop 686 | border 687 | bore 688 | borrow 689 | bosom 690 | boss 691 | botch 692 | bother 693 | bottle 694 | bottleneck 695 | bottom 696 | bounce 697 | bound 698 | bow 699 | bowdlerize 700 | bowel 701 | bower 702 | bowl 703 | bowstring 704 | box 705 | boycott 706 | brace 707 | bracket 708 | brad 709 | brag 710 | braid 711 | braille 712 | brain 713 | brainstorm 714 | brainwash 715 | braise 716 | brake 717 | bramble 718 | bran 719 | branch 720 | brand 721 | brander 722 | brandish 723 | brandy 724 | brave 725 | bravo 726 | brawl 727 | bray 728 | braze 729 | brazen 730 | breach 731 | bread 732 | breadboard 733 | break 734 | breakfast 735 | bream 736 | breast 737 | breathalyze 738 | breathe 739 | breech 740 | breed 741 | breeze 742 | brevet 743 | brew 744 | bribe 745 | brick 746 | bridge 747 | bridle 748 | brief 749 | brigade 750 | brighten 751 | brim 752 | brine 753 | bring 754 | briquet 755 | briquette 756 | brisk 757 | bristle 758 | brittle 759 | broach 760 | broadcast 761 | broaden 762 | broadside 763 | brocade 764 | broil 765 | broker 766 | bronze 767 | brood 768 | brook 769 | broom 770 | browbeat 771 | brown 772 | browse 773 | bruise 774 | bruit 775 | brunch 776 | brush 777 | brutalize 778 | brute 779 | bubble 780 | buck 781 | bucket 782 | buckle 783 | buckler 784 | buckram 785 | bud 786 | buddy 787 | budge 788 | budget 789 | buff 790 | buffalo 791 | buffer 792 | buffet 793 | bug 794 | bugger 795 | bugle 796 | build 797 | bulge 798 | bulk 799 | bull 800 | bulldog 801 | bulldoze 802 | bullet 803 | bulletin 804 | bulletproof 805 | bullshit 806 | bully 807 | bulwark 808 | bum 809 | bumble 810 | bump 811 | bumper 812 | bunch 813 | bunco 814 | bundle 815 | bung 816 | bungle 817 | bunk 818 | bunker 819 | bunko 820 | bunt 821 | buoy 822 | bur 823 | burble 824 | burden 825 | bureaucratize 826 | burgeon 827 | burglarize 828 | burglarproof 829 | burgle 830 | burl 831 | burlesque 832 | burn 833 | burnish 834 | burp 835 | burr 836 | burrow 837 | burst 838 | bury 839 | bus 840 | bush 841 | bushel 842 | bushwhack 843 | buss 844 | bust 845 | bustle 846 | busy 847 | butcher 848 | butt 849 | butter 850 | butterfly 851 | button 852 | buttonhole 853 | buttress 854 | buy 855 | buzz 856 | byline 857 | bypass 858 | cab 859 | cabal 860 | cabbage 861 | cabin 862 | cable 863 | cablecast 864 | cache 865 | cackle 866 | caddie 867 | caddy 868 | cadence 869 | cadge 870 | cage 871 | cajole 872 | cake 873 | cakewalk 874 | calcify 875 | calcimine 876 | calcine 877 | calculate 878 | calendar 879 | calender 880 | calibrate 881 | caliper 882 | calk 883 | call 884 | calliper 885 | callous 886 | callus 887 | calm 888 | calumniate 889 | calve 890 | cam 891 | camber 892 | camouflage 893 | camp 894 | campaign 895 | canal 896 | canalize 897 | cancel 898 | candidate 899 | candle 900 | candy 901 | cane 902 | canker 903 | cannibalize 904 | cannon 905 | cannonade 906 | cannot 907 | canoe 908 | canonize 909 | canopy 910 | cant 911 | canter 912 | cantilever 913 | canton 914 | canvas 915 | canvass 916 | cap 917 | caparison 918 | cape 919 | caper 920 | capitalize 921 | capitulate 922 | capsize 923 | capsule 924 | capsulize 925 | captain 926 | caption 927 | captivate 928 | capture 929 | caramelize 930 | caravan 931 | carbonate 932 | carbonize 933 | carcass 934 | card 935 | care 936 | careen 937 | career 938 | caress 939 | carhop 940 | caricature 941 | carjack 942 | carny 943 | carol 944 | carom 945 | carouse 946 | carp 947 | carpenter 948 | carpet 949 | carpetbag 950 | carpool 951 | carry 952 | cart 953 | carton 954 | cartoon 955 | cartwheel 956 | carve 957 | cascade 958 | case 959 | caseharden 960 | cash 961 | cashier 962 | cask 963 | casket 964 | casserole 965 | cast 966 | castigate 967 | castle 968 | castrate 969 | cat 970 | catalog 971 | catalogue 972 | catalyze 973 | catapult 974 | catcall 975 | catch 976 | catechize 977 | categorize 978 | cater 979 | caterwaul 980 | catheterize 981 | catnap 982 | caucus 983 | caulk 984 | cause 985 | causeway 986 | cauterize 987 | caution 988 | cavalier 989 | cave 990 | cavern 991 | cavil 992 | cavort 993 | caw 994 | cease 995 | cede 996 | celebrate 997 | cellar 998 | cement 999 | censor 1000 | censure 1001 | census 1002 | center 1003 | centralize 1004 | centre 1005 | centrifuge 1006 | cerebrate 1007 | certificate 1008 | certify 1009 | chafe 1010 | chaff 1011 | chagrin 1012 | chain 1013 | chainsaw 1014 | chair 1015 | chairman 1016 | chalk 1017 | challenge 1018 | chamber 1019 | chammy 1020 | chamois 1021 | champ 1022 | champion 1023 | chance 1024 | change 1025 | channel 1026 | channelize 1027 | chant 1028 | chap 1029 | chapel 1030 | chaperon 1031 | chaperone 1032 | chapter 1033 | char 1034 | character 1035 | characterize 1036 | charbroil 1037 | charcoal 1038 | charge 1039 | chariot 1040 | charm 1041 | chart 1042 | charter 1043 | chase 1044 | chasten 1045 | chastise 1046 | chat 1047 | chatter 1048 | chauffeur 1049 | cheapen 1050 | cheat 1051 | check 1052 | checker 1053 | checkerboard 1054 | checkmate 1055 | cheek 1056 | cheep 1057 | cheer 1058 | cherish 1059 | chew 1060 | chicane 1061 | chicken 1062 | chide 1063 | childproof 1064 | chill 1065 | chime 1066 | chimney 1067 | chin 1068 | chine 1069 | chink 1070 | chip 1071 | chipper 1072 | chirp 1073 | chirrup 1074 | chisel 1075 | chitchat 1076 | chlorinate 1077 | chloroform 1078 | chock 1079 | choir 1080 | choke 1081 | chomp 1082 | choose 1083 | chop 1084 | chopper 1085 | chord 1086 | choreograph 1087 | chortle 1088 | chorus 1089 | chow 1090 | christen 1091 | chrome 1092 | chronicle 1093 | chuck 1094 | chuckle 1095 | chug 1096 | chum 1097 | chump 1098 | chunk 1099 | church 1100 | churn 1101 | chute 1102 | cinch 1103 | cincture 1104 | cinder 1105 | cipher 1106 | circle 1107 | circuit 1108 | circularize 1109 | circulate 1110 | circumcise 1111 | circumflex 1112 | circumnavigate 1113 | circumscribe 1114 | circumstance 1115 | circumvent 1116 | cite 1117 | civilise 1118 | civilize 1119 | clack 1120 | clad 1121 | claim 1122 | clam 1123 | clamber 1124 | clamor 1125 | clamour 1126 | clamp 1127 | clang 1128 | clangor 1129 | clangour 1130 | clank 1131 | clap 1132 | clapboard 1133 | clarify 1134 | clash 1135 | clasp 1136 | class 1137 | classify 1138 | clatter 1139 | claw 1140 | clay 1141 | clean 1142 | cleanse 1143 | clear 1144 | cleat 1145 | clench 1146 | clerk 1147 | clew 1148 | click 1149 | climax 1150 | climb 1151 | clinch 1152 | cling 1153 | clink 1154 | clinker 1155 | clique 1156 | cloak 1157 | clobber 1158 | clock 1159 | clog 1160 | cloister 1161 | clomp 1162 | clone 1163 | clonk 1164 | clop 1165 | close 1166 | closet 1167 | closure 1168 | clot 1169 | clothe 1170 | cloture 1171 | cloud 1172 | clout 1173 | clown 1174 | cloy 1175 | club 1176 | cluck 1177 | clue 1178 | clump 1179 | clunk 1180 | cluster 1181 | clutch 1182 | clutter 1183 | coach 1184 | coagulate 1185 | coal 1186 | coalesce 1187 | coarsen 1188 | coast 1189 | coat 1190 | coauthor 1191 | coax 1192 | cobble 1193 | cobweb 1194 | cock 1195 | cockle 1196 | cocktail 1197 | cocoon 1198 | coddle 1199 | code 1200 | codify 1201 | coerce 1202 | coexist 1203 | coffeehouse 1204 | coffer 1205 | coffin 1206 | cog 1207 | cogitate 1208 | cohabit 1209 | cohere 1210 | coif 1211 | coiffure 1212 | coil 1213 | coin 1214 | coincide 1215 | coke 1216 | collaborate 1217 | collage 1218 | collapse 1219 | collar 1220 | collate 1221 | collateralize 1222 | collect 1223 | collectivize 1224 | collide 1225 | collocate 1226 | collude 1227 | colonize 1228 | color 1229 | colorize 1230 | colour 1231 | comb 1232 | combat 1233 | combine 1234 | come 1235 | comfort 1236 | command 1237 | commandeer 1238 | commemorate 1239 | commence 1240 | commend 1241 | comment 1242 | commentate 1243 | commercialize 1244 | commingle 1245 | commiserate 1246 | commission 1247 | commit 1248 | commune 1249 | communicate 1250 | commute 1251 | comp 1252 | compact 1253 | companion 1254 | company 1255 | compare 1256 | compartment 1257 | compartmentalize 1258 | compass 1259 | compassion 1260 | compassionate 1261 | compeer 1262 | compel 1263 | compensate 1264 | compete 1265 | compile 1266 | complain 1267 | complement 1268 | complete 1269 | complex 1270 | complicate 1271 | compliment 1272 | comply 1273 | comport 1274 | compose 1275 | composite 1276 | compost 1277 | compound 1278 | comprehend 1279 | compress 1280 | comprise 1281 | compromise 1282 | compute 1283 | computerize 1284 | con 1285 | concatenate 1286 | concave 1287 | conceal 1288 | concede 1289 | conceit 1290 | conceive 1291 | concentrate 1292 | conceptualize 1293 | concern 1294 | concert 1295 | concertina 1296 | concertize 1297 | conciliate 1298 | conclude 1299 | concoct 1300 | concrete 1301 | concur 1302 | concuss 1303 | condemn 1304 | condense 1305 | condescend 1306 | condition 1307 | condole 1308 | condone 1309 | conduce 1310 | conduct 1311 | cone 1312 | confab 1313 | confabulate 1314 | confection 1315 | confederate 1316 | confer 1317 | conference 1318 | confess 1319 | confide 1320 | configure 1321 | confine 1322 | confirm 1323 | confiscate 1324 | conflate 1325 | conflict 1326 | conform 1327 | confound 1328 | confront 1329 | confuse 1330 | confute 1331 | conga 1332 | congeal 1333 | congest 1334 | conglomerate 1335 | congratulate 1336 | congregate 1337 | congress 1338 | conjecture 1339 | conjoin 1340 | conjugate 1341 | conjure 1342 | conk 1343 | connect 1344 | connive 1345 | connote 1346 | conquer 1347 | conscript 1348 | consecrate 1349 | consent 1350 | conserve 1351 | consider 1352 | consign 1353 | consist 1354 | console 1355 | consolidate 1356 | consort 1357 | conspire 1358 | constipate 1359 | constitute 1360 | constrain 1361 | constrict 1362 | construct 1363 | construe 1364 | consult 1365 | consume 1366 | consummate 1367 | contact 1368 | contain 1369 | containerize 1370 | contaminate 1371 | contemn 1372 | contemplate 1373 | contend 1374 | content 1375 | contest 1376 | contextualize 1377 | continue 1378 | contort 1379 | contour 1380 | contract 1381 | contradict 1382 | contraindicate 1383 | contrast 1384 | contravene 1385 | contribute 1386 | contrive 1387 | control 1388 | controvert 1389 | contuse 1390 | convalesce 1391 | convene 1392 | conventionalize 1393 | converge 1394 | converse 1395 | convert 1396 | convey 1397 | convict 1398 | convince 1399 | convoke 1400 | convoy 1401 | convulse 1402 | coo 1403 | cook 1404 | cool 1405 | coop 1406 | cooper 1407 | cooperate 1408 | coordinate 1409 | cop 1410 | cope 1411 | copper 1412 | copulate 1413 | copy 1414 | copycat 1415 | copyright 1416 | coquette 1417 | corbel 1418 | cord 1419 | cordon 1420 | corduroy 1421 | core 1422 | cork 1423 | corkscrew 1424 | corn 1425 | corner 1426 | cornice 1427 | cornrow 1428 | corral 1429 | correct 1430 | correlate 1431 | correspond 1432 | corroborate 1433 | corrode 1434 | corrugate 1435 | corrupt 1436 | corset 1437 | coruscate 1438 | cosign 1439 | cosponsor 1440 | cosset 1441 | costar 1442 | costume 1443 | cosy 1444 | cote 1445 | cotter 1446 | cotton 1447 | couch 1448 | cough 1449 | counsel 1450 | count 1451 | countenance 1452 | counter 1453 | counteract 1454 | counterattack 1455 | counterbalance 1456 | counterclaim 1457 | counterfeit 1458 | countermand 1459 | counteroffer 1460 | counterpoint 1461 | counterpoise 1462 | countersign 1463 | countersink 1464 | countervail 1465 | counterweight 1466 | coup 1467 | couple 1468 | courier 1469 | course 1470 | court 1471 | courtesy 1472 | cove 1473 | covenant 1474 | cover 1475 | covet 1476 | cow 1477 | cower 1478 | cowhide 1479 | cowl 1480 | coy 1481 | cozen 1482 | cozy 1483 | crab 1484 | crack 1485 | crackle 1486 | cradle 1487 | craft 1488 | cram 1489 | cramp 1490 | crane 1491 | crank 1492 | crap 1493 | crape 1494 | crash 1495 | crate 1496 | crater 1497 | crave 1498 | craven 1499 | crawfish 1500 | crawl 1501 | crayon 1502 | craze 1503 | creak 1504 | cream 1505 | crease 1506 | create 1507 | credential 1508 | credit 1509 | creep 1510 | cremate 1511 | crenelate 1512 | crenellate 1513 | creosote 1514 | crepe 1515 | crescendo 1516 | crest 1517 | crevasse 1518 | crew 1519 | crib 1520 | crick 1521 | cricket 1522 | crimp 1523 | crimson 1524 | cringe 1525 | crinkle 1526 | cripple 1527 | crisp 1528 | crisscross 1529 | criticize 1530 | critique 1531 | croak 1532 | crochet 1533 | crock 1534 | crook 1535 | croon 1536 | crop 1537 | croquet 1538 | cross 1539 | crossbreed 1540 | crosscheck 1541 | crosscut 1542 | crosshatch 1543 | crouch 1544 | crow 1545 | crowbar 1546 | crowd 1547 | crown 1548 | crucify 1549 | crud 1550 | cruise 1551 | crumb 1552 | crumble 1553 | crumple 1554 | crunch 1555 | crusade 1556 | crush 1557 | crust 1558 | crutch 1559 | cry 1560 | crystal 1561 | crystallize 1562 | cub 1563 | cube 1564 | cuckold 1565 | cuckoo 1566 | cuddle 1567 | cudgel 1568 | cue 1569 | cuff 1570 | cull 1571 | culminate 1572 | cultivate 1573 | culture 1574 | cum 1575 | cumber 1576 | cup 1577 | curate 1578 | curb 1579 | curd 1580 | curdle 1581 | cure 1582 | curl 1583 | curlicue 1584 | curry 1585 | currycomb 1586 | curse 1587 | curtail 1588 | curtain 1589 | curtsey 1590 | curtsy 1591 | curve 1592 | cushion 1593 | cuss 1594 | customize 1595 | cut 1596 | cyanide 1597 | cycle 1598 | cylinder 1599 | cypher 1600 | dab 1601 | dabble 1602 | dado 1603 | dagger 1604 | daguerreotype 1605 | dally 1606 | dam 1607 | damage 1608 | damask 1609 | damn 1610 | damp 1611 | dampen 1612 | dance 1613 | dandify 1614 | dandle 1615 | dang 1616 | dangle 1617 | dapple 1618 | dare 1619 | daresay 1620 | dark 1621 | darken 1622 | darn 1623 | dart 1624 | dash 1625 | date 1626 | dateline 1627 | daub 1628 | daunt 1629 | dawdle 1630 | dawn 1631 | daydream 1632 | daylight 1633 | daze 1634 | dazzle 1635 | deacon 1636 | deactivate 1637 | deaden 1638 | deadlock 1639 | deadpan 1640 | deafen 1641 | deal 1642 | debar 1643 | debark 1644 | debase 1645 | debate 1646 | debauch 1647 | debilitate 1648 | debit 1649 | debouch 1650 | debrief 1651 | debug 1652 | debunk 1653 | debut 1654 | decaffeinate 1655 | decal 1656 | decamp 1657 | decant 1658 | decapitate 1659 | decay 1660 | decease 1661 | deceive 1662 | decelerate 1663 | decentralize 1664 | decide 1665 | decimate 1666 | decipher 1667 | decision 1668 | deck 1669 | declaim 1670 | declare 1671 | declassify 1672 | decline 1673 | decode 1674 | decolonize 1675 | decommission 1676 | decompose 1677 | decompress 1678 | decontaminate 1679 | decontrol 1680 | decorate 1681 | decoupage 1682 | decoy 1683 | decrease 1684 | decree 1685 | decriminalize 1686 | decry 1687 | dedicate 1688 | deduce 1689 | deduct 1690 | deed 1691 | deem 1692 | deepen 1693 | deescalate 1694 | deface 1695 | defalcate 1696 | defame 1697 | default 1698 | defeat 1699 | defecate 1700 | defect 1701 | defence 1702 | defend 1703 | defense 1704 | defer 1705 | defile 1706 | define 1707 | deflate 1708 | deflect 1709 | deflower 1710 | defog 1711 | defoliate 1712 | deforest 1713 | deform 1714 | defraud 1715 | defray 1716 | defrock 1717 | defrost 1718 | defuse 1719 | defy 1720 | degas 1721 | degenerate 1722 | degrade 1723 | dehumanize 1724 | dehumidify 1725 | dehydrate 1726 | dehydrogenate 1727 | deice 1728 | deify 1729 | deign 1730 | deject 1731 | delay 1732 | delegate 1733 | delete 1734 | deliberate 1735 | delight 1736 | delimit 1737 | delineate 1738 | deliquesce 1739 | deliver 1740 | delouse 1741 | delude 1742 | deluge 1743 | delve 1744 | demagnetize 1745 | demagog 1746 | demagogue 1747 | demand 1748 | demarcate 1749 | demean 1750 | demilitarize 1751 | demise 1752 | demobilize 1753 | democratize 1754 | demodulate 1755 | demolish 1756 | demonetize 1757 | demonstrate 1758 | demoralize 1759 | demote 1760 | demur 1761 | demystify 1762 | den 1763 | denationalize 1764 | denature 1765 | denigrate 1766 | denizen 1767 | denominate 1768 | denote 1769 | denounce 1770 | dent 1771 | denuclearize 1772 | denude 1773 | deny 1774 | deodorize 1775 | depart 1776 | departmentalize 1777 | depend 1778 | depersonalize 1779 | depict 1780 | deplane 1781 | deplete 1782 | deplore 1783 | deploy 1784 | depolarize 1785 | depoliticize 1786 | depopulate 1787 | deport 1788 | depose 1789 | deposit 1790 | deprave 1791 | deprecate 1792 | depreciate 1793 | depress 1794 | depressurize 1795 | deprive 1796 | deprogram 1797 | depute 1798 | deputize 1799 | derail 1800 | derange 1801 | deregulate 1802 | deride 1803 | derive 1804 | derogate 1805 | derrick 1806 | desalinate 1807 | desalinize 1808 | desalt 1809 | descant 1810 | descend 1811 | describe 1812 | descry 1813 | desecrate 1814 | desegregate 1815 | desensitize 1816 | desert 1817 | deserve 1818 | desiccate 1819 | design 1820 | designate 1821 | desire 1822 | desist 1823 | desolate 1824 | despair 1825 | despatch 1826 | despise 1827 | despite 1828 | despoil 1829 | destabilize 1830 | destine 1831 | destitute 1832 | destroy 1833 | destruct 1834 | detach 1835 | detail 1836 | detain 1837 | detect 1838 | deter 1839 | deteriorate 1840 | determinate 1841 | determine 1842 | detest 1843 | dethrone 1844 | detonate 1845 | detour 1846 | detox 1847 | detoxify 1848 | detract 1849 | devalue 1850 | devastate 1851 | develop 1852 | deviate 1853 | devil 1854 | devise 1855 | devitalize 1856 | devolve 1857 | devote 1858 | devour 1859 | dew 1860 | diadem 1861 | diagnose 1862 | diagram 1863 | dial 1864 | dialog 1865 | dialogue 1866 | diamond 1867 | diaper 1868 | diaphragm 1869 | dibble 1870 | dice 1871 | dick 1872 | dicker 1873 | dictate 1874 | diddle 1875 | die 1876 | diesel 1877 | diet 1878 | differ 1879 | difference 1880 | differentiate 1881 | diffuse 1882 | dig 1883 | digest 1884 | digitize 1885 | dignify 1886 | digress 1887 | dike 1888 | dilate 1889 | dillydally 1890 | dilute 1891 | dim 1892 | dimension 1893 | diminish 1894 | dimple 1895 | din 1896 | dine 1897 | ding 1898 | dinner 1899 | dint 1900 | dip 1901 | diphthong 1902 | diploma 1903 | direct 1904 | dirk 1905 | dirty 1906 | dis 1907 | disable 1908 | disabuse 1909 | disadvantage 1910 | disaffect 1911 | disaffiliate 1912 | disagree 1913 | disallow 1914 | disappear 1915 | disappoint 1916 | disapprove 1917 | disarm 1918 | disarrange 1919 | disarray 1920 | disassemble 1921 | disassociate 1922 | disavow 1923 | disband 1924 | disbar 1925 | disbelieve 1926 | disburse 1927 | disc 1928 | discard 1929 | discern 1930 | discharge 1931 | disciple 1932 | discipline 1933 | disclaim 1934 | disclose 1935 | disco 1936 | discolor 1937 | discolour 1938 | discombobulate 1939 | discomfit 1940 | discomfort 1941 | discommode 1942 | discompose 1943 | disconcert 1944 | disconnect 1945 | discontent 1946 | discontinue 1947 | discord 1948 | discount 1949 | discountenance 1950 | discourage 1951 | discourse 1952 | discover 1953 | discredit 1954 | discriminate 1955 | discuss 1956 | disdain 1957 | disease 1958 | disembark 1959 | disembody 1960 | disembowel 1961 | disenchant 1962 | disencumber 1963 | disenfranchise 1964 | disengage 1965 | disentangle 1966 | disestablish 1967 | disesteem 1968 | disfavor 1969 | disfigure 1970 | disfranchise 1971 | disgorge 1972 | disgrace 1973 | disgruntle 1974 | disguise 1975 | disgust 1976 | dish 1977 | dishearten 1978 | dishevel 1979 | dishonor 1980 | disillusion 1981 | disincline 1982 | disinfect 1983 | disinherit 1984 | disintegrate 1985 | disinter 1986 | disinterest 1987 | disjoint 1988 | disk 1989 | dislike 1990 | dislocate 1991 | dislodge 1992 | dismantle 1993 | dismay 1994 | dismember 1995 | dismiss 1996 | dismount 1997 | disobey 1998 | disoblige 1999 | disorder 2000 | disorganize 2001 | disorient 2002 | disorientate 2003 | disown 2004 | disparage 2005 | dispatch 2006 | dispel 2007 | dispense 2008 | disperse 2009 | dispirit 2010 | displace 2011 | display 2012 | displease 2013 | displeasure 2014 | disport 2015 | dispose 2016 | dispossess 2017 | dispraise 2018 | disproportion 2019 | disprove 2020 | dispute 2021 | disqualify 2022 | disquiet 2023 | disregard 2024 | disrespect 2025 | disrobe 2026 | disrupt 2027 | diss 2028 | dissatisfy 2029 | dissect 2030 | dissemble 2031 | disseminate 2032 | dissent 2033 | dissever 2034 | dissimulate 2035 | dissipate 2036 | dissociate 2037 | dissolve 2038 | dissuade 2039 | distance 2040 | distaste 2041 | distemper 2042 | distend 2043 | distil 2044 | distill 2045 | distinguish 2046 | distort 2047 | distract 2048 | distress 2049 | distribute 2050 | district 2051 | distrust 2052 | disturb 2053 | disunite 2054 | disuse 2055 | ditch 2056 | dither 2057 | ditto 2058 | ditty 2059 | dive 2060 | diverge 2061 | diversify 2062 | divert 2063 | divest 2064 | divide 2065 | divine 2066 | divorce 2067 | divulge 2068 | divvy 2069 | dizzy 2070 | do 2071 | dock 2072 | docket 2073 | doctor 2074 | document 2075 | dodder 2076 | dodge 2077 | doff 2078 | dog 2079 | dogear 2080 | doggone 2081 | dogleg 2082 | dogtrot 2083 | dole 2084 | doll 2085 | dollop 2086 | dolly 2087 | dome 2088 | domesticate 2089 | domicile 2090 | dominate 2091 | domineer 2092 | don 2093 | donate 2094 | doodle 2095 | doom 2096 | doorstep 2097 | dope 2098 | dose 2099 | dot 2100 | dote 2101 | double 2102 | doubt 2103 | douche 2104 | douse 2105 | dovetail 2106 | dowel 2107 | dower 2108 | down 2109 | downgrade 2110 | download 2111 | downplay 2112 | downscale 2113 | downshift 2114 | downsize 2115 | dowse 2116 | doze 2117 | dozen 2118 | drab 2119 | draft 2120 | drag 2121 | dragoon 2122 | drain 2123 | dram 2124 | dramatize 2125 | drape 2126 | drat 2127 | draught 2128 | draw 2129 | drawl 2130 | dray 2131 | dread 2132 | dream 2133 | dredge 2134 | drench 2135 | dress 2136 | dribble 2137 | drift 2138 | drill 2139 | drink 2140 | drip 2141 | drive 2142 | drivel 2143 | drizzle 2144 | droll 2145 | drone 2146 | drool 2147 | droop 2148 | drop 2149 | drove 2150 | drown 2151 | drowse 2152 | drub 2153 | drudge 2154 | drug 2155 | drum 2156 | dry 2157 | dub 2158 | duck 2159 | duct 2160 | dude 2161 | duel 2162 | duet 2163 | duff 2164 | dull 2165 | dumbfound 2166 | dumfound 2167 | dummy 2168 | dump 2169 | dun 2170 | dung 2171 | dunk 2172 | dupe 2173 | duplex 2174 | duplicate 2175 | dusk 2176 | dust 2177 | dwarf 2178 | dwell 2179 | dwindle 2180 | dye 2181 | dyke 2182 | dynamite 2183 | eagle 2184 | ear 2185 | earmark 2186 | earn 2187 | earth 2188 | earwig 2189 | ease 2190 | eat 2191 | eavesdrop 2192 | ebb 2193 | echelon 2194 | echo 2195 | eclipse 2196 | economize 2197 | eddy 2198 | edge 2199 | edify 2200 | edit 2201 | editorialize 2202 | educate 2203 | educe 2204 | efface 2205 | effect 2206 | effectuate 2207 | effeminate 2208 | effervesce 2209 | effuse 2210 | egg 2211 | egress 2212 | ejaculate 2213 | eject 2214 | eke 2215 | elaborate 2216 | elapse 2217 | elasticize 2218 | elate 2219 | elbow 2220 | elect 2221 | electioneer 2222 | electrify 2223 | electrocute 2224 | electroplate 2225 | electroshock 2226 | electrotype 2227 | elevate 2228 | elicit 2229 | elide 2230 | eliminate 2231 | elongate 2232 | elope 2233 | elucidate 2234 | elude 2235 | emaciate 2236 | email 2237 | emanate 2238 | emancipate 2239 | emasculate 2240 | embalm 2241 | embank 2242 | embargo 2243 | embark 2244 | embarrass 2245 | embed 2246 | embellish 2247 | embezzle 2248 | embitter 2249 | emblazon 2250 | emblem 2251 | embody 2252 | embolden 2253 | emboss 2254 | embower 2255 | embrace 2256 | embroider 2257 | embroil 2258 | emcee 2259 | emend 2260 | emerge 2261 | emigrate 2262 | emit 2263 | emote 2264 | emotionalize 2265 | empanel 2266 | empathize 2267 | emphasize 2268 | employ 2269 | empower 2270 | empty 2271 | emulate 2272 | emulsify 2273 | enable 2274 | enact 2275 | enamel 2276 | enamor 2277 | enamour 2278 | encamp 2279 | encapsulate 2280 | encase 2281 | enchain 2282 | enchant 2283 | encipher 2284 | encircle 2285 | enclave 2286 | enclose 2287 | encode 2288 | encompass 2289 | encore 2290 | encounter 2291 | encourage 2292 | encroach 2293 | encrust 2294 | encumber 2295 | encyst 2296 | end 2297 | endanger 2298 | endear 2299 | endeavor 2300 | endeavour 2301 | endorse 2302 | endow 2303 | endue 2304 | endure 2305 | energize 2306 | enervate 2307 | enfeeble 2308 | enfilade 2309 | enfold 2310 | enforce 2311 | enfranchise 2312 | engage 2313 | engender 2314 | engineer 2315 | engorge 2316 | engrave 2317 | engross 2318 | engulf 2319 | enhance 2320 | enjoin 2321 | enjoy 2322 | enlarge 2323 | enlighten 2324 | enlist 2325 | enliven 2326 | enmesh 2327 | ennoble 2328 | enplane 2329 | enquire 2330 | enrage 2331 | enrapture 2332 | enrich 2333 | enrol 2334 | enroll 2335 | ensconce 2336 | enshrine 2337 | enshroud 2338 | ensilage 2339 | enslave 2340 | ensnare 2341 | ensue 2342 | ensure 2343 | entail 2344 | entangle 2345 | enter 2346 | entertain 2347 | enthral 2348 | enthrall 2349 | enthrone 2350 | enthuse 2351 | entice 2352 | entitle 2353 | entomb 2354 | entrance 2355 | entrap 2356 | entreat 2357 | entrench 2358 | entrust 2359 | entwine 2360 | enumerate 2361 | enunciate 2362 | enure 2363 | envelop 2364 | envenom 2365 | envisage 2366 | envision 2367 | envy 2368 | epitaph 2369 | epitomize 2370 | epoxy 2371 | equal 2372 | equalize 2373 | equate 2374 | equip 2375 | equipoise 2376 | equivocate 2377 | eradicate 2378 | erase 2379 | erect 2380 | erode 2381 | err 2382 | eruct 2383 | erupt 2384 | escalate 2385 | escallop 2386 | escalop 2387 | escape 2388 | eschew 2389 | escort 2390 | escrow 2391 | espalier 2392 | espouse 2393 | espy 2394 | esquire 2395 | essay 2396 | establish 2397 | estate 2398 | esteem 2399 | estimate 2400 | estrange 2401 | etch 2402 | euchre 2403 | eulogize 2404 | euthanize 2405 | evacuate 2406 | evade 2407 | evaluate 2408 | evangelize 2409 | evaporate 2410 | even 2411 | eventuate 2412 | evict 2413 | evidence 2414 | evince 2415 | eviscerate 2416 | evoke 2417 | evolve 2418 | exacerbate 2419 | exact 2420 | exaggerate 2421 | exalt 2422 | examine 2423 | example 2424 | exasperate 2425 | excavate 2426 | exceed 2427 | excel 2428 | except 2429 | excerpt 2430 | excess 2431 | exchange 2432 | excise 2433 | excite 2434 | exclaim 2435 | exclude 2436 | excommunicate 2437 | excoriate 2438 | excrete 2439 | exculpate 2440 | excursion 2441 | excuse 2442 | execrate 2443 | execute 2444 | exemplify 2445 | exempt 2446 | exercise 2447 | exert 2448 | exhale 2449 | exhaust 2450 | exhibit 2451 | exhilarate 2452 | exhort 2453 | exhume 2454 | exile 2455 | exist 2456 | exit 2457 | exonerate 2458 | exorcise 2459 | exorcize 2460 | expand 2461 | expatiate 2462 | expatriate 2463 | expect 2464 | expectorate 2465 | expedite 2466 | expel 2467 | expend 2468 | expense 2469 | experience 2470 | experiment 2471 | expert 2472 | expertise 2473 | expiate 2474 | expire 2475 | explain 2476 | explicate 2477 | explode 2478 | exploit 2479 | explore 2480 | export 2481 | expose 2482 | expostulate 2483 | expound 2484 | express 2485 | expropriate 2486 | expunge 2487 | expurgate 2488 | extemporize 2489 | extend 2490 | extenuate 2491 | exterminate 2492 | externalize 2493 | extinct 2494 | extinguish 2495 | extirpate 2496 | extol 2497 | extoll 2498 | extort 2499 | extract 2500 | extradite 2501 | extrapolate 2502 | extravert 2503 | extricate 2504 | extrovert 2505 | extrude 2506 | exude 2507 | exult 2508 | eye 2509 | eyeball 2510 | eyelet 2511 | fable 2512 | fabricate 2513 | face 2514 | facelift 2515 | facet 2516 | facilitate 2517 | facsimile 2518 | factor 2519 | fade 2520 | fag 2521 | fail 2522 | faint 2523 | fair 2524 | fake 2525 | fall 2526 | fallow 2527 | falsify 2528 | falter 2529 | fame 2530 | familiarize 2531 | famish 2532 | fan 2533 | fancy 2534 | fang 2535 | fantasize 2536 | fantasy 2537 | farce 2538 | fare 2539 | farewell 2540 | farm 2541 | farrow 2542 | fart 2543 | fascinate 2544 | fashion 2545 | fast 2546 | fasten 2547 | fat 2548 | fate 2549 | father 2550 | fathom 2551 | fatigue 2552 | fatten 2553 | fault 2554 | favor 2555 | favour 2556 | fawn 2557 | fax 2558 | faze 2559 | fear 2560 | feast 2561 | feather 2562 | feature 2563 | fecundate 2564 | federalize 2565 | federate 2566 | fee 2567 | feed 2568 | feel 2569 | feign 2570 | feint 2571 | felicitate 2572 | fell 2573 | fellow 2574 | fellowship 2575 | felt 2576 | fence 2577 | fend 2578 | ferment 2579 | ferret 2580 | ferrule 2581 | ferry 2582 | fertilize 2583 | ferule 2584 | fess 2585 | fester 2586 | festoon 2587 | fetch 2588 | fete 2589 | fetter 2590 | fettle 2591 | feud 2592 | fever 2593 | fib 2594 | fiberglass 2595 | fibrillate 2596 | fictionalize 2597 | fiddle 2598 | fidget 2599 | field 2600 | fife 2601 | fight 2602 | figure 2603 | filch 2604 | file 2605 | filet 2606 | filibuster 2607 | filigree 2608 | fill 2609 | fillet 2610 | fillip 2611 | film 2612 | filter 2613 | filthy 2614 | filtrate 2615 | fin 2616 | finagle 2617 | finalize 2618 | finance 2619 | financier 2620 | find 2621 | fine 2622 | finesse 2623 | finger 2624 | fingerprint 2625 | finish 2626 | fink 2627 | fire 2628 | firebomb 2629 | fireproof 2630 | firm 2631 | fish 2632 | fishtail 2633 | fission 2634 | fissure 2635 | fist 2636 | fit 2637 | fix 2638 | fixate 2639 | fizz 2640 | fizzle 2641 | flabbergast 2642 | flack 2643 | flag 2644 | flagellate 2645 | flail 2646 | flake 2647 | flambe 2648 | flame 2649 | flameproof 2650 | flange 2651 | flank 2652 | flannel 2653 | flap 2654 | flare 2655 | flash 2656 | flat 2657 | flatten 2658 | flatter 2659 | flaunt 2660 | flavor 2661 | flavour 2662 | flaw 2663 | flay 2664 | fleck 2665 | flee 2666 | fleece 2667 | fleet 2668 | flesh 2669 | flex 2670 | flick 2671 | flicker 2672 | flight 2673 | flimflam 2674 | flinch 2675 | fling 2676 | flint 2677 | flip 2678 | flirt 2679 | flit 2680 | float 2681 | flock 2682 | flog 2683 | flood 2684 | floodlight 2685 | floor 2686 | flop 2687 | floss 2688 | flounce 2689 | flounder 2690 | flour 2691 | flourish 2692 | flout 2693 | flow 2694 | flower 2695 | flub 2696 | fluctuate 2697 | fluff 2698 | flume 2699 | flummox 2700 | flunk 2701 | fluoresce 2702 | fluoridate 2703 | fluoroscope 2704 | flurry 2705 | flush 2706 | fluster 2707 | flute 2708 | flutter 2709 | flux 2710 | flyspeck 2711 | foal 2712 | foam 2713 | fob 2714 | focus 2715 | fodder 2716 | fog 2717 | foil 2718 | foist 2719 | fold 2720 | folio 2721 | follow 2722 | foment 2723 | fondle 2724 | fool 2725 | foot 2726 | football 2727 | footnote 2728 | forage 2729 | foray 2730 | forbear 2731 | forbid 2732 | force 2733 | ford 2734 | forearm 2735 | forebode 2736 | forecast 2737 | foreclose 2738 | foredoom 2739 | foregather 2740 | forego 2741 | foreground 2742 | foreknow 2743 | forelock 2744 | foreordain 2745 | foresee 2746 | foreshadow 2747 | foreshorten 2748 | forest 2749 | forestall 2750 | foreswear 2751 | foretaste 2752 | foretell 2753 | forewarn 2754 | forfeit 2755 | forgather 2756 | forge 2757 | forget 2758 | forgive 2759 | forgo 2760 | fork 2761 | forklift 2762 | form 2763 | formalize 2764 | format 2765 | formulate 2766 | fornicate 2767 | forsake 2768 | forswear 2769 | fortify 2770 | fortune 2771 | forward 2772 | fossilize 2773 | foster 2774 | foul 2775 | found 2776 | founder 2777 | fowl 2778 | fox 2779 | foxtrot 2780 | fraction 2781 | fracture 2782 | fragment 2783 | frame 2784 | franchise 2785 | frank 2786 | frappe 2787 | fraternize 2788 | fray 2789 | frazzle 2790 | freak 2791 | freckle 2792 | free 2793 | freebase 2794 | freelance 2795 | freeload 2796 | freewheel 2797 | freeze 2798 | freight 2799 | frenzy 2800 | frequent 2801 | fresco 2802 | fresh 2803 | freshen 2804 | fret 2805 | fricassee 2806 | friend 2807 | frig 2808 | fright 2809 | frighten 2810 | frill 2811 | fringe 2812 | frisk 2813 | fritter 2814 | friz 2815 | frizz 2816 | frizzle 2817 | frock 2818 | frog 2819 | frolic 2820 | front 2821 | frost 2822 | frostbite 2823 | froth 2824 | frown 2825 | fructify 2826 | fruit 2827 | frustrate 2828 | fry 2829 | fuck 2830 | fuddle 2831 | fudge 2832 | fuel 2833 | fugue 2834 | fulcrum 2835 | fulfil 2836 | fulfill 2837 | full 2838 | fuller 2839 | fulminate 2840 | fumble 2841 | fume 2842 | fumigate 2843 | fun 2844 | function 2845 | fund 2846 | funk 2847 | funnel 2848 | fur 2849 | furbelow 2850 | furbish 2851 | furl 2852 | furlough 2853 | furnace 2854 | furnish 2855 | furrow 2856 | further 2857 | fuse 2858 | fusillade 2859 | fuss 2860 | futz 2861 | fuze 2862 | fuzz 2863 | gab 2864 | gabble 2865 | gad 2866 | gaff 2867 | gag 2868 | gage 2869 | gaggle 2870 | gain 2871 | gainsay 2872 | gait 2873 | gall 2874 | gallant 2875 | gallivant 2876 | gallop 2877 | galumph 2878 | galvanise 2879 | galvanize 2880 | gamble 2881 | gambol 2882 | game 2883 | gammon 2884 | gander 2885 | gang 2886 | gangrene 2887 | gantlet 2888 | gaol 2889 | gap 2890 | gape 2891 | gar 2892 | garage 2893 | garb 2894 | garble 2895 | garden 2896 | gargle 2897 | garland 2898 | garment 2899 | garner 2900 | garnish 2901 | garnishee 2902 | garote 2903 | garotte 2904 | garrison 2905 | garrote 2906 | garrotte 2907 | garter 2908 | gas 2909 | gash 2910 | gasp 2911 | gate 2912 | gatecrash 2913 | gather 2914 | gauge 2915 | gauntlet 2916 | gavel 2917 | gavotte 2918 | gawk 2919 | gaze 2920 | gazette 2921 | gear 2922 | gee 2923 | gel 2924 | geld 2925 | gem 2926 | gender 2927 | generalize 2928 | generate 2929 | gentle 2930 | gentrify 2931 | genuflect 2932 | germinate 2933 | gerrymander 2934 | gestate 2935 | gesticulate 2936 | gesture 2937 | get 2938 | geyser 2939 | ghetto 2940 | ghettoize 2941 | ghost 2942 | ghostwrite 2943 | gibber 2944 | gibbet 2945 | gibe 2946 | giddy 2947 | gift 2948 | gig 2949 | giggle 2950 | gild 2951 | gill 2952 | gimlet 2953 | gimmick 2954 | gimp 2955 | gin 2956 | ginger 2957 | gipsy 2958 | gird 2959 | girdle 2960 | girt 2961 | girth 2962 | give 2963 | glace 2964 | glaciate 2965 | glad 2966 | gladden 2967 | glamorize 2968 | glamourize 2969 | glance 2970 | glare 2971 | glass 2972 | glaze 2973 | gleam 2974 | glean 2975 | glee 2976 | glide 2977 | glimmer 2978 | glimpse 2979 | glint 2980 | glisten 2981 | glister 2982 | glitter 2983 | glitz 2984 | gloat 2985 | globalize 2986 | globe 2987 | gloom 2988 | glorify 2989 | glory 2990 | gloss 2991 | glove 2992 | glow 2993 | glower 2994 | glue 2995 | glut 2996 | gnarl 2997 | gnash 2998 | gnaw 2999 | go 3000 | goad 3001 | gob 3002 | gobble 3003 | god 3004 | goddamn 3005 | godfather 3006 | goggle 3007 | goldbrick 3008 | golf 3009 | gong 3010 | goof 3011 | goose 3012 | gopher 3013 | gore 3014 | gorge 3015 | gormandize 3016 | gospel 3017 | gossip 3018 | gouge 3019 | govern 3020 | governess 3021 | gown 3022 | grab 3023 | grace 3024 | gradate 3025 | grade 3026 | graduate 3027 | graft 3028 | grain 3029 | grandfather 3030 | grandstand 3031 | grant 3032 | granulate 3033 | graph 3034 | grapple 3035 | grasp 3036 | grass 3037 | grate 3038 | gratify 3039 | grave 3040 | gravel 3041 | gravitate 3042 | gray 3043 | graze 3044 | grease 3045 | green 3046 | greet 3047 | grey 3048 | griddle 3049 | gridiron 3050 | grieve 3051 | grill 3052 | grimace 3053 | grime 3054 | grin 3055 | grind 3056 | grip 3057 | gripe 3058 | grit 3059 | groan 3060 | groin 3061 | grommet 3062 | groom 3063 | groove 3064 | grope 3065 | gross 3066 | grouch 3067 | ground 3068 | group 3069 | grouse 3070 | grout 3071 | grovel 3072 | grow 3073 | growl 3074 | grub 3075 | grubstake 3076 | grudge 3077 | grumble 3078 | grump 3079 | grunt 3080 | guarantee 3081 | guaranty 3082 | guard 3083 | guess 3084 | guesstimate 3085 | guest 3086 | guffaw 3087 | guide 3088 | guillotine 3089 | guilt 3090 | guise 3091 | gulf 3092 | gull 3093 | gullet 3094 | gully 3095 | gulp 3096 | gum 3097 | gumshoe 3098 | gun 3099 | gurgle 3100 | gush 3101 | gusset 3102 | gussy 3103 | gust 3104 | gut 3105 | guts 3106 | gutter 3107 | guy 3108 | guzzle 3109 | gyp 3110 | gypsy 3111 | gyrate 3112 | gyve 3113 | habit 3114 | habituate 3115 | hack 3116 | hackle 3117 | hackney 3118 | haemorrhage 3119 | haft 3120 | haggle 3121 | hail 3122 | hale 3123 | hallmark 3124 | hallo 3125 | halloo 3126 | hallow 3127 | hallucinate 3128 | halo 3129 | halt 3130 | halter 3131 | halve 3132 | ham 3133 | hammer 3134 | hamper 3135 | hamstring 3136 | hand 3137 | handcraft 3138 | handcuff 3139 | handicap 3140 | handle 3141 | handpick 3142 | handset 3143 | hang 3144 | hangar 3145 | hank 3146 | hanker 3147 | hap 3148 | happen 3149 | harangue 3150 | harass 3151 | harbinger 3152 | harbor 3153 | harbour 3154 | harden 3155 | hare 3156 | hark 3157 | harken 3158 | harm 3159 | harmonize 3160 | harness 3161 | harp 3162 | harpoon 3163 | harrow 3164 | harry 3165 | harvest 3166 | hash 3167 | hasp 3168 | hassle 3169 | haste 3170 | hasten 3171 | hat 3172 | hatch 3173 | hatchet 3174 | hate 3175 | haul 3176 | haunt 3177 | have 3178 | haven 3179 | havoc 3180 | haw 3181 | hawk 3182 | hay 3183 | hazard 3184 | haze 3185 | head 3186 | headhunt 3187 | headline 3188 | headquarter 3189 | heal 3190 | heap 3191 | hear 3192 | hearken 3193 | hearten 3194 | heat 3195 | heatproof 3196 | heave 3197 | heckle 3198 | hector 3199 | hedge 3200 | hedgehop 3201 | heed 3202 | heehaw 3203 | heel 3204 | heft 3205 | heighten 3206 | heir 3207 | heist 3208 | helicopter 3209 | hello 3210 | helm 3211 | help 3212 | helve 3213 | hem 3214 | hemorrhage 3215 | hemstitch 3216 | henna 3217 | henpeck 3218 | herald 3219 | herd 3220 | herniate 3221 | hesitate 3222 | hew 3223 | hex 3224 | hibernate 3225 | hiccough 3226 | hiccup 3227 | hide 3228 | hie 3229 | highball 3230 | highjack 3231 | highlight 3232 | hightail 3233 | hijack 3234 | hike 3235 | hill 3236 | hilltop 3237 | hilt 3238 | hinder 3239 | hinge 3240 | hint 3241 | hip 3242 | hire 3243 | hiss 3244 | hit 3245 | hitch 3246 | hitchhike 3247 | hive 3248 | hoard 3249 | hoax 3250 | hob 3251 | hobble 3252 | hobnail 3253 | hobnob 3254 | hock 3255 | hoe 3256 | hog 3257 | hogtie 3258 | hoist 3259 | hoke 3260 | hold 3261 | hole 3262 | holiday 3263 | holler 3264 | hollow 3265 | holograph 3266 | holster 3267 | home 3268 | homer 3269 | homestead 3270 | homogenize 3271 | honcho 3272 | hone 3273 | honey 3274 | honeycomb 3275 | honeymoon 3276 | honk 3277 | honor 3278 | honour 3279 | hood 3280 | hoodoo 3281 | hoodwink 3282 | hoof 3283 | hook 3284 | hoop 3285 | hooray 3286 | hoot 3287 | hop 3288 | hope 3289 | hopscotch 3290 | horde 3291 | horn 3292 | horrify 3293 | horse 3294 | horselaugh 3295 | horseshoe 3296 | horsewhip 3297 | hosanna 3298 | hose 3299 | hospitalize 3300 | host 3301 | hostage 3302 | hostel 3303 | hostess 3304 | hot 3305 | hotdog 3306 | hotfoot 3307 | hound 3308 | house 3309 | housebreak 3310 | houseclean 3311 | hovel 3312 | hover 3313 | howl 3314 | hub 3315 | huckster 3316 | huddle 3317 | huff 3318 | hug 3319 | hulk 3320 | hull 3321 | hullo 3322 | hum 3323 | humanize 3324 | humble 3325 | humbug 3326 | humidify 3327 | humiliate 3328 | humor 3329 | humour 3330 | hump 3331 | humph 3332 | hunch 3333 | hunger 3334 | hunker 3335 | hunt 3336 | hurdle 3337 | hurl 3338 | hurrah 3339 | hurray 3340 | hurry 3341 | hurt 3342 | hurtle 3343 | husband 3344 | hush 3345 | husk 3346 | hustle 3347 | hut 3348 | huzza 3349 | huzzah 3350 | hybridize 3351 | hydrate 3352 | hydrogenate 3353 | hydrolyze 3354 | hydroplane 3355 | hymn 3356 | hype 3357 | hypertrophy 3358 | hyperventilate 3359 | hyphen 3360 | hyphenate 3361 | hypnotize 3362 | hypo 3363 | hypothesize 3364 | ice 3365 | idealize 3366 | identify 3367 | idle 3368 | idolize 3369 | ignite 3370 | ignore 3371 | illegitimate 3372 | illuminate 3373 | illumine 3374 | illustrate 3375 | image 3376 | imagine 3377 | imbed 3378 | imbibe 3379 | imbue 3380 | imitate 3381 | immerse 3382 | immigrate 3383 | immobilize 3384 | immolate 3385 | immortalize 3386 | immunize 3387 | immure 3388 | imp 3389 | impact 3390 | impair 3391 | impale 3392 | impanel 3393 | impart 3394 | impeach 3395 | impede 3396 | impel 3397 | impend 3398 | imperil 3399 | impersonate 3400 | impinge 3401 | implant 3402 | implement 3403 | implicate 3404 | implode 3405 | implore 3406 | imply 3407 | import 3408 | importune 3409 | impose 3410 | impost 3411 | impound 3412 | impoverish 3413 | imprecate 3414 | impregnate 3415 | impress 3416 | imprint 3417 | imprison 3418 | improve 3419 | improvise 3420 | impugn 3421 | impulse 3422 | impute 3423 | inactivate 3424 | inaugurate 3425 | inbound 3426 | inbreed 3427 | incapacitate 3428 | incarcerate 3429 | incarnadine 3430 | incarnate 3431 | incense 3432 | inch 3433 | incinerate 3434 | incise 3435 | incite 3436 | incline 3437 | inclose 3438 | include 3439 | incommode 3440 | inconvenience 3441 | incorporate 3442 | increase 3443 | incriminate 3444 | incrust 3445 | incubate 3446 | inculcate 3447 | inculpate 3448 | incumber 3449 | incur 3450 | indemnify 3451 | indent 3452 | indenture 3453 | index 3454 | indicate 3455 | indict 3456 | indirect 3457 | indite 3458 | individualize 3459 | individuate 3460 | indoctrinate 3461 | indorse 3462 | induce 3463 | induct 3464 | indue 3465 | indulge 3466 | indulgence 3467 | industrialize 3468 | indwell 3469 | inebriate 3470 | infatuate 3471 | infect 3472 | infer 3473 | infest 3474 | infiltrate 3475 | infirm 3476 | inflame 3477 | inflate 3478 | inflect 3479 | inflict 3480 | influence 3481 | infold 3482 | inform 3483 | infringe 3484 | infuriate 3485 | infuse 3486 | ingest 3487 | ingot 3488 | ingrain 3489 | ingratiate 3490 | inhabit 3491 | inhale 3492 | inhere 3493 | inherit 3494 | inhibit 3495 | initial 3496 | initialize 3497 | initiate 3498 | inject 3499 | injure 3500 | ink 3501 | inlay 3502 | inlet 3503 | innervate 3504 | innovate 3505 | inoculate 3506 | input 3507 | inquire 3508 | inscribe 3509 | inseminate 3510 | insert 3511 | inset 3512 | insinuate 3513 | insist 3514 | inspect 3515 | inspire 3516 | inspirit 3517 | instal 3518 | install 3519 | instance 3520 | instantiate 3521 | instate 3522 | instigate 3523 | instil 3524 | instill 3525 | institute 3526 | institutionalize 3527 | instruct 3528 | instrument 3529 | insulate 3530 | insult 3531 | insure 3532 | intaglio 3533 | integrate 3534 | intellectualize 3535 | intend 3536 | intensify 3537 | inter 3538 | interact 3539 | interbreed 3540 | intercede 3541 | intercept 3542 | interchange 3543 | intercommunicate 3544 | interconnect 3545 | interdict 3546 | interest 3547 | interface 3548 | interfere 3549 | interfile 3550 | interject 3551 | interlace 3552 | interlard 3553 | interleave 3554 | interline 3555 | interlink 3556 | interlock 3557 | interlope 3558 | intermarry 3559 | intermediate 3560 | intermingle 3561 | intermix 3562 | intern 3563 | internalize 3564 | internationalise 3565 | internationalize 3566 | interne 3567 | interplay 3568 | interpolate 3569 | interpose 3570 | interpret 3571 | interrelate 3572 | interrogate 3573 | interrupt 3574 | intersect 3575 | intersperse 3576 | intertwine 3577 | intervene 3578 | interview 3579 | interweave 3580 | intimate 3581 | intimidate 3582 | intone 3583 | intoxicate 3584 | intrench 3585 | intrigue 3586 | introduce 3587 | introspect 3588 | introvert 3589 | intrude 3590 | intrust 3591 | intuit 3592 | inundate 3593 | inure 3594 | invade 3595 | invalid 3596 | invalidate 3597 | inveigh 3598 | inveigle 3599 | invent 3600 | inventory 3601 | inverse 3602 | invert 3603 | invest 3604 | investigate 3605 | invigorate 3606 | invite 3607 | invoice 3608 | invoke 3609 | involve 3610 | iodize 3611 | ionize 3612 | iris 3613 | irk 3614 | iron 3615 | irradiate 3616 | irrigate 3617 | irritate 3618 | irrupt 3619 | island 3620 | isle 3621 | isolate 3622 | issue 3623 | italicize 3624 | itch 3625 | item 3626 | itemize 3627 | iterate 3628 | jab 3629 | jabber 3630 | jack 3631 | jacket 3632 | jackknife 3633 | jackrabbit 3634 | jade 3635 | jag 3636 | jail 3637 | jam 3638 | jangle 3639 | japan 3640 | jape 3641 | jar 3642 | jargon 3643 | jaundice 3644 | jaunt 3645 | javelin 3646 | jaw 3647 | jawbone 3648 | jaywalk 3649 | jazz 3650 | jeep 3651 | jeer 3652 | jell 3653 | jelly 3654 | jeopardize 3655 | jerk 3656 | jest 3657 | jet 3658 | jettison 3659 | jetty 3660 | jewel 3661 | jib 3662 | jibe 3663 | jig 3664 | jigger 3665 | jiggle 3666 | jigsaw 3667 | jilt 3668 | jimmy 3669 | jingle 3670 | jinx 3671 | jitney 3672 | jitterbug 3673 | jive 3674 | job 3675 | jockey 3676 | jog 3677 | joggle 3678 | join 3679 | joint 3680 | joist 3681 | joke 3682 | jolly 3683 | jolt 3684 | josh 3685 | jostle 3686 | jot 3687 | jounce 3688 | journal 3689 | journey 3690 | joust 3691 | joy 3692 | joyride 3693 | judge 3694 | jug 3695 | juggle 3696 | juice 3697 | julienne 3698 | jumble 3699 | jump 3700 | junk 3701 | junket 3702 | junketeer 3703 | jury 3704 | just 3705 | justify 3706 | jut 3707 | juxtapose 3708 | kayak 3709 | kayo 3710 | keel 3711 | keelhaul 3712 | keen 3713 | keep 3714 | kelp 3715 | ken 3716 | kennel 3717 | kerb 3718 | kernel 3719 | key 3720 | keyboard 3721 | keynote 3722 | keypunch 3723 | kibble 3724 | kibitz 3725 | kibosh 3726 | kick 3727 | kid 3728 | kidnap 3729 | kill 3730 | kiln 3731 | kilt 3732 | kindle 3733 | king 3734 | kink 3735 | kip 3736 | kipper 3737 | kiss 3738 | kit 3739 | kite 3740 | kitten 3741 | knead 3742 | knee 3743 | kneecap 3744 | kneel 3745 | knell 3746 | knife 3747 | knight 3748 | knit 3749 | knock 3750 | knoll 3751 | knot 3752 | know 3753 | knuckle 3754 | knurl 3755 | kosher 3756 | kowtow 3757 | kraal 3758 | kvetch 3759 | label 3760 | labor 3761 | labour 3762 | lace 3763 | lacerate 3764 | lack 3765 | lackey 3766 | lacquer 3767 | lactate 3768 | ladder 3769 | lade 3770 | laden 3771 | ladle 3772 | lag 3773 | lager 3774 | lair 3775 | lallygag 3776 | lam 3777 | lamb 3778 | lambast 3779 | lambaste 3780 | lame 3781 | lament 3782 | laminate 3783 | lamp 3784 | lampoon 3785 | lance 3786 | land 3787 | landfill 3788 | landmark 3789 | landscape 3790 | landslide 3791 | languish 3792 | lantern 3793 | lap 3794 | lapse 3795 | lard 3796 | lark 3797 | lash 3798 | lasso 3799 | last 3800 | latch 3801 | lateral 3802 | lath 3803 | lathe 3804 | lather 3805 | lattice 3806 | laud 3807 | laugh 3808 | launch 3809 | launder 3810 | laurel 3811 | lave 3812 | lavish 3813 | law 3814 | lawyer 3815 | lay 3816 | layer 3817 | laze 3818 | lazy 3819 | leach 3820 | lead 3821 | leaden 3822 | leaf 3823 | leaflet 3824 | league 3825 | leak 3826 | lean 3827 | leap 3828 | leapfrog 3829 | learn 3830 | lease 3831 | leash 3832 | leather 3833 | leave 3834 | leaven 3835 | lech 3836 | lecher 3837 | lecture 3838 | ledge 3839 | leech 3840 | leer 3841 | leg 3842 | legalize 3843 | legislate 3844 | legitimate 3845 | legitimatize 3846 | legitimize 3847 | lend 3848 | lengthen 3849 | lens 3850 | lesion 3851 | lessen 3852 | lesson 3853 | let 3854 | letter 3855 | levee 3856 | level 3857 | lever 3858 | leverage 3859 | levitate 3860 | levy 3861 | liaise 3862 | libel 3863 | liberalize 3864 | liberate 3865 | licence 3866 | license 3867 | lichen 3868 | lick 3869 | lid 3870 | lifeguard 3871 | lift 3872 | ligate 3873 | ligature 3874 | light 3875 | lighten 3876 | lighter 3877 | lightning 3878 | like 3879 | liken 3880 | lilt 3881 | limb 3882 | limber 3883 | lime 3884 | limit 3885 | limn 3886 | limp 3887 | line 3888 | linger 3889 | link 3890 | lionize 3891 | lip 3892 | lipread 3893 | liquefy 3894 | liquidate 3895 | liquidize 3896 | liquify 3897 | liquor 3898 | lisp 3899 | list 3900 | listen 3901 | lithograph 3902 | litigate 3903 | litter 3904 | live 3905 | liven 3906 | liver 3907 | load 3908 | loaf 3909 | loam 3910 | loan 3911 | loathe 3912 | lob 3913 | lobby 3914 | lobotomize 3915 | local 3916 | localize 3917 | locate 3918 | lock 3919 | loco 3920 | lodge 3921 | loft 3922 | log 3923 | loiter 3924 | loll 3925 | lollygag 3926 | long 3927 | look 3928 | loom 3929 | loop 3930 | loophole 3931 | loose 3932 | loosen 3933 | loot 3934 | lop 3935 | lope 3936 | lord 3937 | lose 3938 | lot 3939 | lounge 3940 | lour 3941 | lout 3942 | louver 3943 | love 3944 | low 3945 | lower 3946 | lowercase 3947 | lube 3948 | lubricate 3949 | luck 3950 | lucubrate 3951 | luff 3952 | lug 3953 | lull 3954 | lullaby 3955 | lumber 3956 | lump 3957 | lunch 3958 | lunge 3959 | lurch 3960 | lure 3961 | lurk 3962 | lush 3963 | lust 3964 | luster 3965 | lustre 3966 | lute 3967 | luxuriate 3968 | lynch 3969 | macadamize 3970 | mace 3971 | macerate 3972 | machinate 3973 | machine 3974 | macrame 3975 | mad 3976 | madden 3977 | mag 3978 | magnetise 3979 | magnetize 3980 | magnify 3981 | mail 3982 | maim 3983 | main 3984 | mainline 3985 | mainstream 3986 | maintain 3987 | major 3988 | make 3989 | malfunction 3990 | malign 3991 | malinger 3992 | malt 3993 | maltreat 3994 | mambo 3995 | man 3996 | manacle 3997 | manage 3998 | mandamus 3999 | mandate 4000 | maneuver 4001 | mangle 4002 | manhandle 4003 | manicure 4004 | manifest 4005 | manifold 4006 | manipulate 4007 | manoeuvre 4008 | mantle 4009 | manufacture 4010 | manumit 4011 | manure 4012 | map 4013 | mar 4014 | maraud 4015 | marble 4016 | marbleize 4017 | march 4018 | margin 4019 | marginalize 4020 | marinade 4021 | marinate 4022 | mark 4023 | market 4024 | marl 4025 | maroon 4026 | marry 4027 | marshal 4028 | martyr 4029 | marvel 4030 | mascara 4031 | mash 4032 | mask 4033 | mason 4034 | masquerade 4035 | mass 4036 | massacre 4037 | massage 4038 | mast 4039 | master 4040 | mastermind 4041 | masthead 4042 | masticate 4043 | masturbate 4044 | mat 4045 | match 4046 | mate 4047 | materialise 4048 | materialize 4049 | matriculate 4050 | matt 4051 | matte 4052 | matter 4053 | maturate 4054 | mature 4055 | maul 4056 | maunder 4057 | max 4058 | maximize 4059 | may 4060 | maze 4061 | mean 4062 | meander 4063 | measure 4064 | mechanize 4065 | medal 4066 | meddle 4067 | mediate 4068 | medicate 4069 | medicine 4070 | meditate 4071 | meet 4072 | megaphone 4073 | meld 4074 | meliorate 4075 | mellow 4076 | melt 4077 | memorialize 4078 | memorize 4079 | menace 4080 | mend 4081 | menstruate 4082 | mention 4083 | mentor 4084 | meow 4085 | mercerize 4086 | merchandise 4087 | merchandize 4088 | merge 4089 | meringue 4090 | merit 4091 | mesh 4092 | mesmerize 4093 | mess 4094 | message 4095 | messenger 4096 | metabolize 4097 | metal 4098 | metamorphose 4099 | metastasize 4100 | mete 4101 | meter 4102 | methinks 4103 | metre 4104 | metricate 4105 | metricize 4106 | mew 4107 | mewl 4108 | microfilm 4109 | micromanage 4110 | microwave 4111 | middle 4112 | midwife 4113 | miff 4114 | migrate 4115 | mike 4116 | mildew 4117 | militarize 4118 | militate 4119 | milk 4120 | mill 4121 | milt 4122 | mime 4123 | mimeograph 4124 | mimic 4125 | mince 4126 | mind 4127 | mine 4128 | mingle 4129 | miniaturize 4130 | minimize 4131 | minister 4132 | minor 4133 | mint 4134 | minute 4135 | mire 4136 | mirror 4137 | misaddress 4138 | misapply 4139 | misapprehend 4140 | misappropriate 4141 | misbehave 4142 | miscalculate 4143 | miscall 4144 | miscarry 4145 | miscast 4146 | misconceive 4147 | misconduct 4148 | misconstrue 4149 | miscount 4150 | miscue 4151 | misdeal 4152 | misdiagnose 4153 | misdirect 4154 | misdo 4155 | misfile 4156 | misfire 4157 | misfit 4158 | misgovern 4159 | misguide 4160 | mishandle 4161 | mishear 4162 | misidentify 4163 | misinform 4164 | misinterpret 4165 | misjudge 4166 | mislabel 4167 | mislay 4168 | mislead 4169 | mismanage 4170 | mismatch 4171 | misname 4172 | misplace 4173 | misplay 4174 | misprint 4175 | mispronounce 4176 | misquote 4177 | misread 4178 | misreport 4179 | misrepresent 4180 | misrule 4181 | miss 4182 | misshape 4183 | missing 4184 | misspeak 4185 | misspell 4186 | misspend 4187 | misstate 4188 | mist 4189 | mistake 4190 | mister 4191 | mistime 4192 | mistreat 4193 | mistrust 4194 | misunderstand 4195 | misuse 4196 | miter 4197 | mitigate 4198 | mitre 4199 | mix 4200 | moan 4201 | mob 4202 | mobilize 4203 | mock 4204 | model 4205 | modem 4206 | moderate 4207 | modernize 4208 | modify 4209 | modulate 4210 | moil 4211 | moisten 4212 | moisturize 4213 | mold 4214 | molder 4215 | molest 4216 | mollify 4217 | mollycoddle 4218 | molt 4219 | monetize 4220 | monger 4221 | monitor 4222 | monkey 4223 | monogram 4224 | monograph 4225 | monopolize 4226 | montage 4227 | monument 4228 | moo 4229 | mooch 4230 | moon 4231 | moonlight 4232 | moonwalk 4233 | moor 4234 | moot 4235 | mop 4236 | mope 4237 | moralize 4238 | mordant 4239 | morph 4240 | morsel 4241 | mortar 4242 | mortgage 4243 | mortice 4244 | mortify 4245 | mortise 4246 | mosaic 4247 | mosey 4248 | mosh 4249 | moss 4250 | mothball 4251 | mother 4252 | motion 4253 | motivate 4254 | motive 4255 | motor 4256 | motorbike 4257 | motorboat 4258 | motorcade 4259 | motorcycle 4260 | motorize 4261 | mottle 4262 | mould 4263 | moulder 4264 | moult 4265 | mound 4266 | mount 4267 | mountaineer 4268 | mountebank 4269 | mourn 4270 | mouse 4271 | mousetrap 4272 | mousse 4273 | mouth 4274 | move 4275 | mow 4276 | muck 4277 | muckrake 4278 | mud 4279 | muddle 4280 | muddy 4281 | muff 4282 | muffle 4283 | mug 4284 | mugger 4285 | mulch 4286 | mulct 4287 | mull 4288 | mullion 4289 | multiplex 4290 | multiply 4291 | mum 4292 | mumble 4293 | mummify 4294 | mummy 4295 | munch 4296 | munition 4297 | murder 4298 | murmur 4299 | muscle 4300 | muse 4301 | mush 4302 | mushroom 4303 | muss 4304 | muster 4305 | mutate 4306 | mute 4307 | mutilate 4308 | mutiny 4309 | mutter 4310 | muzzle 4311 | mystify 4312 | mythologize 4313 | nab 4314 | nag 4315 | nail 4316 | name 4317 | namedrop 4318 | nap 4319 | napalm 4320 | narc 4321 | narcotize 4322 | nark 4323 | narrate 4324 | narrow 4325 | nasalize 4326 | nationalize 4327 | natter 4328 | naturalize 4329 | nauseate 4330 | navigate 4331 | near 4332 | neaten 4333 | necessitate 4334 | neck 4335 | necklace 4336 | need 4337 | needle 4338 | negate 4339 | negative 4340 | neglect 4341 | negotiate 4342 | neigh 4343 | neighbor 4344 | neighbour 4345 | nerve 4346 | nest 4347 | nestle 4348 | net 4349 | nett 4350 | nettle 4351 | network 4352 | neuter 4353 | neutralize 4354 | nibble 4355 | niche 4356 | nick 4357 | nickel 4358 | nicker 4359 | nickname 4360 | nigger 4361 | niggle 4362 | nigh 4363 | nightclub 4364 | nip 4365 | nitpick 4366 | nitrate 4367 | nix 4368 | nod 4369 | noise 4370 | nominate 4371 | nonplus 4372 | noodle 4373 | noose 4374 | normalize 4375 | nose 4376 | nosedive 4377 | nosh 4378 | notarize 4379 | notate 4380 | notch 4381 | note 4382 | notice 4383 | notify 4384 | nourish 4385 | novelize 4386 | nucleate 4387 | nudge 4388 | nuke 4389 | null 4390 | nullify 4391 | numb 4392 | number 4393 | numerate 4394 | nurse 4395 | nursemaid 4396 | nurture 4397 | nut 4398 | nuzzle 4399 | oar 4400 | obey 4401 | obfuscate 4402 | object 4403 | objectify 4404 | objurgate 4405 | obligate 4406 | oblige 4407 | oblique 4408 | obliterate 4409 | obscure 4410 | observe 4411 | obsess 4412 | obsolesce 4413 | obsolete 4414 | obstruct 4415 | obtain 4416 | obtrude 4417 | obviate 4418 | occasion 4419 | occlude 4420 | occult 4421 | occupy 4422 | occur 4423 | ocher 4424 | ochre 4425 | off 4426 | offend 4427 | offer 4428 | officer 4429 | officiate 4430 | offload 4431 | offprint 4432 | offset 4433 | ogle 4434 | oil 4435 | oink 4436 | okay 4437 | omen 4438 | omit 4439 | ooh 4440 | ooze 4441 | opaque 4442 | ope 4443 | open 4444 | operate 4445 | opiate 4446 | opine 4447 | oppose 4448 | oppress 4449 | opt 4450 | optimize 4451 | option 4452 | orate 4453 | orb 4454 | orbit 4455 | orchestrate 4456 | ordain 4457 | order 4458 | organize 4459 | orgasm 4460 | orient 4461 | orientate 4462 | originate 4463 | ornament 4464 | orphan 4465 | oscillate 4466 | osculate 4467 | ossify 4468 | ostracize 4469 | ouch 4470 | ought 4471 | oust 4472 | out 4473 | outargue 4474 | outbalance 4475 | outbid 4476 | outboast 4477 | outbox 4478 | outclass 4479 | outcrop 4480 | outcry 4481 | outdistance 4482 | outdo 4483 | outdraw 4484 | outface 4485 | outfight 4486 | outfit 4487 | outflank 4488 | outfox 4489 | outgrow 4490 | outguess 4491 | outgun 4492 | outhit 4493 | outlast 4494 | outlaw 4495 | outlay 4496 | outline 4497 | outlive 4498 | outmaneuver 4499 | outmanoeuvre 4500 | outmatch 4501 | outnumber 4502 | outperform 4503 | outplace 4504 | outplay 4505 | outpoint 4506 | outproduce 4507 | output 4508 | outrace 4509 | outrage 4510 | outrank 4511 | outreach 4512 | outrun 4513 | outscore 4514 | outsell 4515 | outshine 4516 | outshout 4517 | outsmart 4518 | outsource 4519 | outspend 4520 | outspread 4521 | outstay 4522 | outstretch 4523 | outstrip 4524 | outvote 4525 | outwear 4526 | outweigh 4527 | outwit 4528 | outwork 4529 | over 4530 | overachieve 4531 | overact 4532 | overarm 4533 | overawe 4534 | overbalance 4535 | overbear 4536 | overbid 4537 | overbook 4538 | overbuild 4539 | overburden 4540 | overbuy 4541 | overcapitalize 4542 | overcast 4543 | overcharge 4544 | overcloud 4545 | overcoat 4546 | overcome 4547 | overcompensate 4548 | overcook 4549 | overcrowd 4550 | overdecorate 4551 | overdevelop 4552 | overdo 4553 | overdose 4554 | overdraw 4555 | overdress 4556 | overdrive 4557 | overdub 4558 | overeat 4559 | overemphasize 4560 | overestimate 4561 | overexcite 4562 | overexercise 4563 | overexert 4564 | overexpose 4565 | overextend 4566 | overfeed 4567 | overfill 4568 | overflow 4569 | overfly 4570 | overgeneralize 4571 | overgraze 4572 | overgrow 4573 | overhand 4574 | overhang 4575 | overhaul 4576 | overhear 4577 | overheat 4578 | overindulge 4579 | overjoy 4580 | overlap 4581 | overlay 4582 | overlie 4583 | overload 4584 | overlook 4585 | overlord 4586 | overmaster 4587 | overnight 4588 | overpass 4589 | overpay 4590 | overplay 4591 | overpopulate 4592 | overpower 4593 | overpraise 4594 | overprice 4595 | overprint 4596 | overproduce 4597 | overprotect 4598 | overrate 4599 | overreach 4600 | overreact 4601 | override 4602 | overrule 4603 | overrun 4604 | oversee 4605 | oversell 4606 | overshadow 4607 | overshoot 4608 | oversimplify 4609 | oversleep 4610 | overspecialize 4611 | overspend 4612 | overspill 4613 | overspread 4614 | overstate 4615 | overstay 4616 | overstep 4617 | overstimulate 4618 | overstock 4619 | oversubscribe 4620 | oversupply 4621 | overtake 4622 | overtax 4623 | overthrow 4624 | overtime 4625 | overtire 4626 | overture 4627 | overturn 4628 | overuse 4629 | overvalue 4630 | overweight 4631 | overwhelm 4632 | overwinter 4633 | overwork 4634 | ovulate 4635 | owe 4636 | owl 4637 | own 4638 | oxidize 4639 | oxygenate 4640 | oyster 4641 | pace 4642 | pacify 4643 | pack 4644 | package 4645 | packet 4646 | pad 4647 | paddle 4648 | paddock 4649 | padlock 4650 | page 4651 | paginate 4652 | pain 4653 | paint 4654 | pair 4655 | pal 4656 | palatalize 4657 | palaver 4658 | pale 4659 | palisade 4660 | pall 4661 | pallet 4662 | palliate 4663 | palm 4664 | palpate 4665 | palpitate 4666 | palsy 4667 | pamper 4668 | pamphlet 4669 | pamphleteer 4670 | pan 4671 | pancake 4672 | pander 4673 | panel 4674 | panhandle 4675 | panic 4676 | pant 4677 | pantomime 4678 | paper 4679 | par 4680 | parachute 4681 | parade 4682 | paraffin 4683 | paragon 4684 | paragraph 4685 | parallel 4686 | paralyse 4687 | paralyze 4688 | paraphrase 4689 | parboil 4690 | parcel 4691 | parch 4692 | pardon 4693 | pare 4694 | parent 4695 | parenthesize 4696 | park 4697 | parlay 4698 | parley 4699 | parody 4700 | parole 4701 | parquet 4702 | parrot 4703 | parry 4704 | parse 4705 | part 4706 | partake 4707 | participate 4708 | particularize 4709 | partition 4710 | partner 4711 | party 4712 | pass 4713 | passage 4714 | paste 4715 | pasteurize 4716 | pastor 4717 | pasture 4718 | pat 4719 | patch 4720 | patent 4721 | patrol 4722 | patronize 4723 | patter 4724 | pattern 4725 | pauper 4726 | pauperize 4727 | pause 4728 | pave 4729 | pavilion 4730 | paw 4731 | pawn 4732 | pay 4733 | peace 4734 | peach 4735 | peacock 4736 | peak 4737 | peal 4738 | pearl 4739 | pebble 4740 | peck 4741 | peculate 4742 | pedal 4743 | peddle 4744 | pedestal 4745 | pedestrianize 4746 | pedicure 4747 | pee 4748 | peek 4749 | peel 4750 | peen 4751 | peep 4752 | peer 4753 | peeve 4754 | peg 4755 | pellet 4756 | pelt 4757 | pen 4758 | penalize 4759 | pencil 4760 | pend 4761 | penetrate 4762 | pension 4763 | people 4764 | pep 4765 | pepper 4766 | perambulate 4767 | perceive 4768 | perch 4769 | percolate 4770 | peregrinate 4771 | perfect 4772 | perforate 4773 | perform 4774 | perfume 4775 | peril 4776 | perish 4777 | perjure 4778 | perk 4779 | perm 4780 | permeate 4781 | permit 4782 | permute 4783 | peroxide 4784 | perpetrate 4785 | perpetuate 4786 | perplex 4787 | persecute 4788 | persevere 4789 | persist 4790 | personalize 4791 | personify 4792 | perspire 4793 | persuade 4794 | pertain 4795 | perturb 4796 | peruse 4797 | pervade 4798 | pervert 4799 | pester 4800 | pestle 4801 | pet 4802 | peter 4803 | petition 4804 | petrify 4805 | petrol 4806 | pettifog 4807 | phantasy 4808 | phase 4809 | philander 4810 | philosophize 4811 | philter 4812 | philtre 4813 | phone 4814 | phoney 4815 | phony 4816 | photo 4817 | photocopy 4818 | photoengrave 4819 | photograph 4820 | photostat 4821 | photosynthesize 4822 | phrase 4823 | physic 4824 | pi 4825 | pick 4826 | pickaback 4827 | pickax 4828 | pickaxe 4829 | picket 4830 | pickle 4831 | picnic 4832 | picture 4833 | piddle 4834 | pie 4835 | piece 4836 | pierce 4837 | piffle 4838 | pig 4839 | pigeonhole 4840 | piggyback 4841 | pigment 4842 | pike 4843 | pile 4844 | pilfer 4845 | pilgrimage 4846 | pill 4847 | pillage 4848 | pillar 4849 | pillory 4850 | pillow 4851 | pilot 4852 | pimp 4853 | pin 4854 | pincer 4855 | pinch 4856 | pine 4857 | ping 4858 | pinion 4859 | pink 4860 | pinnacle 4861 | pinpoint 4862 | pinwheel 4863 | pioneer 4864 | pip 4865 | pipe 4866 | pipeline 4867 | pipette 4868 | pique 4869 | pirate 4870 | pirouette 4871 | piss 4872 | pistol 4873 | pit 4874 | pitapat 4875 | pitch 4876 | pitchfork 4877 | pith 4878 | pity 4879 | pivot 4880 | placard 4881 | placate 4882 | place 4883 | placekick 4884 | plagiarize 4885 | plague 4886 | plain 4887 | plait 4888 | plan 4889 | plane 4890 | plank 4891 | plant 4892 | plash 4893 | plaster 4894 | plasticize 4895 | plat 4896 | plate 4897 | plateau 4898 | platform 4899 | platoon 4900 | play 4901 | playact 4902 | plead 4903 | please 4904 | pleasure 4905 | pleat 4906 | pledge 4907 | plight 4908 | plod 4909 | plop 4910 | plot 4911 | plough 4912 | plow 4913 | ploy 4914 | pluck 4915 | plug 4916 | plumb 4917 | plume 4918 | plummet 4919 | plump 4920 | plunder 4921 | plunge 4922 | plunk 4923 | pluralize 4924 | ply 4925 | poach 4926 | pocket 4927 | pockmark 4928 | pod 4929 | point 4930 | poise 4931 | poison 4932 | poke 4933 | polarize 4934 | pole 4935 | police 4936 | polish 4937 | politicize 4938 | polka 4939 | poll 4940 | pollen 4941 | pollinate 4942 | pollute 4943 | polygraph 4944 | polymerize 4945 | pomade 4946 | pommel 4947 | pond 4948 | ponder 4949 | poniard 4950 | pontificate 4951 | pony 4952 | pooh 4953 | pool 4954 | poop 4955 | pop 4956 | popularize 4957 | populate 4958 | pore 4959 | porpoise 4960 | port 4961 | portage 4962 | portend 4963 | portion 4964 | portray 4965 | pose 4966 | posit 4967 | position 4968 | possess 4969 | post 4970 | postcard 4971 | postdate 4972 | postmark 4973 | postpone 4974 | postulate 4975 | posture 4976 | pot 4977 | pother 4978 | pothole 4979 | potter 4980 | pouch 4981 | poultice 4982 | pounce 4983 | pound 4984 | pour 4985 | pout 4986 | powder 4987 | power 4988 | powwow 4989 | practice 4990 | practise 4991 | praise 4992 | prance 4993 | prank 4994 | prate 4995 | prattle 4996 | prawn 4997 | pray 4998 | preach 4999 | prearrange 5000 | precancel 5001 | precaution 5002 | precede 5003 | precipitate 5004 | precis 5005 | preclude 5006 | preconceive 5007 | precondition 5008 | precook 5009 | predate 5010 | predecease 5011 | predesignate 5012 | predestine 5013 | predetermine 5014 | predicate 5015 | predict 5016 | predigest 5017 | predispose 5018 | predominate 5019 | preempt 5020 | preen 5021 | preexist 5022 | prefab 5023 | prefabricate 5024 | preface 5025 | prefer 5026 | prefigure 5027 | prefix 5028 | preform 5029 | preheat 5030 | prejudge 5031 | prejudice 5032 | prelude 5033 | premeditate 5034 | premier 5035 | premiere 5036 | premise 5037 | premix 5038 | preoccupy 5039 | preordain 5040 | prep 5041 | prepackage 5042 | prepare 5043 | prepay 5044 | preponderate 5045 | prepossess 5046 | prerecord 5047 | preregister 5048 | presage 5049 | prescribe 5050 | present 5051 | preserve 5052 | preset 5053 | preshrink 5054 | preside 5055 | presort 5056 | press 5057 | pressure 5058 | pressurize 5059 | presume 5060 | presuppose 5061 | pretend 5062 | pretension 5063 | pretest 5064 | prettify 5065 | pretty 5066 | prevail 5067 | prevaricate 5068 | prevent 5069 | preview 5070 | prevue 5071 | prey 5072 | price 5073 | prick 5074 | prickle 5075 | pride 5076 | priest 5077 | prig 5078 | prim 5079 | prime 5080 | primp 5081 | print 5082 | prioritize 5083 | prise 5084 | privateer 5085 | privatize 5086 | privilege 5087 | prize 5088 | probate 5089 | probe 5090 | proceed 5091 | process 5092 | procession 5093 | proclaim 5094 | procrastinate 5095 | procreate 5096 | proctor 5097 | procure 5098 | prod 5099 | produce 5100 | profane 5101 | profess 5102 | professionalize 5103 | proffer 5104 | profile 5105 | profit 5106 | profiteer 5107 | prognosticate 5108 | program 5109 | programme 5110 | progress 5111 | prohibit 5112 | project 5113 | prolapse 5114 | proliferate 5115 | prolog 5116 | prologue 5117 | prolong 5118 | promenade 5119 | promise 5120 | promo 5121 | promote 5122 | prompt 5123 | promulgate 5124 | prong 5125 | pronounce 5126 | proof 5127 | proofread 5128 | prop 5129 | propagandize 5130 | propagate 5131 | propel 5132 | prophesy 5133 | propitiate 5134 | proportion 5135 | proportionate 5136 | propose 5137 | proposition 5138 | propound 5139 | prorate 5140 | prorogue 5141 | proscribe 5142 | prose 5143 | prosecute 5144 | proselyte 5145 | proselytize 5146 | prospect 5147 | prosper 5148 | prostitute 5149 | prostrate 5150 | protect 5151 | protest 5152 | protocol 5153 | prototype 5154 | protract 5155 | protrude 5156 | prove 5157 | proverb 5158 | provide 5159 | provision 5160 | provoke 5161 | prowl 5162 | prune 5163 | pry 5164 | psalm 5165 | pshaw 5166 | psych 5167 | psyche 5168 | psychoanalyze 5169 | publicize 5170 | publish 5171 | pucker 5172 | puddle 5173 | puff 5174 | pug 5175 | puke 5176 | pule 5177 | pull 5178 | pulp 5179 | pulsate 5180 | pulse 5181 | pulverize 5182 | pumice 5183 | pummel 5184 | pump 5185 | pun 5186 | punch 5187 | punctuate 5188 | puncture 5189 | punish 5190 | punt 5191 | pup 5192 | purchase 5193 | puree 5194 | purge 5195 | purify 5196 | purl 5197 | purloin 5198 | purple 5199 | purport 5200 | purpose 5201 | purr 5202 | purse 5203 | pursue 5204 | purvey 5205 | push 5206 | pussyfoot 5207 | put 5208 | putrefy 5209 | putt 5210 | putter 5211 | putty 5212 | puzzle 5213 | pyramid 5214 | quack 5215 | quad 5216 | quadruple 5217 | quadruplicate 5218 | quaff 5219 | quail 5220 | quake 5221 | qualify 5222 | quantify 5223 | quarantine 5224 | quarrel 5225 | quarry 5226 | quarter 5227 | quarterback 5228 | quash 5229 | quaver 5230 | queen 5231 | queer 5232 | quell 5233 | quench 5234 | query 5235 | quest 5236 | question 5237 | queue 5238 | quibble 5239 | quicken 5240 | quicksilver 5241 | quiet 5242 | quill 5243 | quilt 5244 | quintuple 5245 | quip 5246 | quire 5247 | quirk 5248 | quirt 5249 | quit 5250 | quitclaim 5251 | quiver 5252 | quiz 5253 | quoin 5254 | quoit 5255 | quote 5256 | quoth 5257 | rabbet 5258 | rabble 5259 | race 5260 | rack 5261 | racket 5262 | racketeer 5263 | radiate 5264 | radicalize 5265 | radio 5266 | radiotelegraph 5267 | radiotelephone 5268 | raffle 5269 | raft 5270 | rafter 5271 | rag 5272 | rage 5273 | ragout 5274 | raid 5275 | rail 5276 | railroad 5277 | raiment 5278 | rain 5279 | rainproof 5280 | raise 5281 | rake 5282 | rally 5283 | ram 5284 | ramble 5285 | ramify 5286 | ramp 5287 | rampage 5288 | rampart 5289 | ramrod 5290 | ranch 5291 | randomize 5292 | range 5293 | rank 5294 | rankle 5295 | ransack 5296 | ransom 5297 | rant 5298 | rap 5299 | rape 5300 | rappel 5301 | rapture 5302 | rare 5303 | rarefy 5304 | rasp 5305 | rat 5306 | ratchet 5307 | rate 5308 | ratify 5309 | ratiocinate 5310 | ration 5311 | rationalize 5312 | rattle 5313 | ravage 5314 | rave 5315 | ravel 5316 | raven 5317 | ravish 5318 | rawhide 5319 | ray 5320 | raze 5321 | razor 5322 | razz 5323 | reabsorb 5324 | reach 5325 | reacquaint 5326 | reacquire 5327 | react 5328 | reactivate 5329 | read 5330 | readdress 5331 | readjust 5332 | readmit 5333 | readopt 5334 | ready 5335 | reaffirm 5336 | realign 5337 | realize 5338 | reallocate 5339 | ream 5340 | reanalyze 5341 | reanimate 5342 | reap 5343 | reappear 5344 | reapply 5345 | reappoint 5346 | reapportion 5347 | reappraise 5348 | rear 5349 | rearm 5350 | rearrange 5351 | rearrest 5352 | reascend 5353 | reason 5354 | reassemble 5355 | reassert 5356 | reassess 5357 | reassign 5358 | reassure 5359 | reattach 5360 | reattain 5361 | reattempt 5362 | reauthorize 5363 | reawaken 5364 | rebate 5365 | rebel 5366 | rebid 5367 | rebind 5368 | reboil 5369 | reboot 5370 | rebound 5371 | rebroadcast 5372 | rebuff 5373 | rebuild 5374 | rebuke 5375 | rebury 5376 | rebut 5377 | recalculate 5378 | recall 5379 | recant 5380 | recap 5381 | recapitalize 5382 | recapitulate 5383 | recapture 5384 | recast 5385 | recede 5386 | receipt 5387 | receive 5388 | recess 5389 | recharge 5390 | recharter 5391 | recheck 5392 | rechristen 5393 | reciprocate 5394 | recirculate 5395 | recite 5396 | reckon 5397 | reclaim 5398 | reclassify 5399 | recline 5400 | recognize 5401 | recoil 5402 | recollect 5403 | recolonize 5404 | recolor 5405 | recombine 5406 | recommence 5407 | recommend 5408 | recommission 5409 | recommit 5410 | recompense 5411 | recompose 5412 | recompute 5413 | reconcile 5414 | recondition 5415 | reconfirm 5416 | reconnect 5417 | reconnoiter 5418 | reconnoitre 5419 | reconquer 5420 | reconsecrate 5421 | reconsider 5422 | reconsign 5423 | reconstitute 5424 | reconstruct 5425 | recontact 5426 | recontaminate 5427 | reconvene 5428 | reconvert 5429 | recook 5430 | recopy 5431 | record 5432 | recount 5433 | recoup 5434 | recover 5435 | recreate 5436 | recriminate 5437 | recross 5438 | recrudesce 5439 | recruit 5440 | recrystallize 5441 | rectify 5442 | recuperate 5443 | recur 5444 | recycle 5445 | red 5446 | redact 5447 | redden 5448 | redecorate 5449 | rededicate 5450 | redeem 5451 | redefine 5452 | redeliver 5453 | redeploy 5454 | redeposit 5455 | redesign 5456 | redetermine 5457 | redevelop 5458 | redial 5459 | redirect 5460 | rediscover 5461 | redissolve 5462 | redistribute 5463 | redistrict 5464 | redivide 5465 | redo 5466 | redouble 5467 | redound 5468 | redraft 5469 | redraw 5470 | redress 5471 | reduce 5472 | reduplicate 5473 | redye 5474 | reecho 5475 | reed 5476 | reedit 5477 | reeducate 5478 | reef 5479 | reek 5480 | reel 5481 | reelect 5482 | reembark 5483 | reembody 5484 | reemerge 5485 | reemphasize 5486 | reemploy 5487 | reenact 5488 | reenforce 5489 | reengage 5490 | reenlist 5491 | reenter 5492 | reequip 5493 | reestablish 5494 | reevaluate 5495 | reeve 5496 | reexamine 5497 | reexplain 5498 | reexport 5499 | ref 5500 | reface 5501 | refashion 5502 | refasten 5503 | refer 5504 | referee 5505 | reference 5506 | refile 5507 | refill 5508 | refinance 5509 | refine 5510 | refinish 5511 | refit 5512 | reflect 5513 | reflex 5514 | refocus 5515 | refold 5516 | reforest 5517 | reforge 5518 | reform 5519 | reformulate 5520 | refortify 5521 | refract 5522 | refrain 5523 | refreeze 5524 | refresh 5525 | refrigerate 5526 | refuel 5527 | refuge 5528 | refund 5529 | refurbish 5530 | refurnish 5531 | refuse 5532 | refute 5533 | regain 5534 | regale 5535 | regard 5536 | regather 5537 | regenerate 5538 | regiment 5539 | register 5540 | regrade 5541 | regress 5542 | regret 5543 | regrind 5544 | regroup 5545 | regrow 5546 | regularise 5547 | regularize 5548 | regulate 5549 | regurgitate 5550 | rehab 5551 | rehabilitate 5552 | rehang 5553 | rehash 5554 | rehear 5555 | rehearse 5556 | reheat 5557 | rehire 5558 | rehouse 5559 | reign 5560 | reignite 5561 | reimburse 5562 | reimpose 5563 | rein 5564 | reincarnate 5565 | reincorporate 5566 | reinfect 5567 | reinforce 5568 | reinoculate 5569 | reinsert 5570 | reinspect 5571 | reinstate 5572 | reintegrate 5573 | reinterpret 5574 | reintroduce 5575 | reinvent 5576 | reinvest 5577 | reinvigorate 5578 | reissue 5579 | reiterate 5580 | reject 5581 | rejoice 5582 | rejoin 5583 | rejudge 5584 | rejuvenate 5585 | rekindle 5586 | relabel 5587 | relapse 5588 | relate 5589 | relaunch 5590 | relax 5591 | relay 5592 | relearn 5593 | release 5594 | relegate 5595 | relent 5596 | relieve 5597 | relight 5598 | reline 5599 | relinquish 5600 | relish 5601 | relive 5602 | reload 5603 | relocate 5604 | rely 5605 | remain 5606 | remainder 5607 | remake 5608 | remand 5609 | remap 5610 | remark 5611 | remarry 5612 | rematch 5613 | remeasure 5614 | remedy 5615 | remelt 5616 | remember 5617 | remigrate 5618 | remind 5619 | reminisce 5620 | remit 5621 | remix 5622 | remodel 5623 | remold 5624 | remonstrate 5625 | remount 5626 | remove 5627 | remunerate 5628 | rename 5629 | rend 5630 | render 5631 | rendezvous 5632 | renege 5633 | renegotiate 5634 | renew 5635 | renominate 5636 | renounce 5637 | renovate 5638 | rent 5639 | renumber 5640 | reoccupy 5641 | reoccur 5642 | reopen 5643 | reorder 5644 | reorganize 5645 | reorient 5646 | repack 5647 | repackage 5648 | repaint 5649 | repair 5650 | repatriate 5651 | repave 5652 | repay 5653 | repeal 5654 | repeat 5655 | repel 5656 | repent 5657 | rephotograph 5658 | rephrase 5659 | repine 5660 | replace 5661 | replant 5662 | replay 5663 | replenish 5664 | replicate 5665 | reply 5666 | repopulate 5667 | report 5668 | repose 5669 | repossess 5670 | reprehend 5671 | represent 5672 | repress 5673 | reprice 5674 | reprieve 5675 | reprimand 5676 | reprint 5677 | reprise 5678 | reproach 5679 | reprobate 5680 | reprocess 5681 | reproduce 5682 | reprogram 5683 | reprove 5684 | republish 5685 | repudiate 5686 | repulse 5687 | repurchase 5688 | repute 5689 | request 5690 | require 5691 | requisition 5692 | requite 5693 | reread 5694 | rerecord 5695 | reroute 5696 | rerun 5697 | reschedule 5698 | rescind 5699 | rescue 5700 | reseal 5701 | research 5702 | reseed 5703 | resell 5704 | resemble 5705 | resent 5706 | reserve 5707 | reset 5708 | resettle 5709 | resew 5710 | reshape 5711 | resharpen 5712 | reship 5713 | reshuffle 5714 | reside 5715 | resign 5716 | resin 5717 | resist 5718 | resole 5719 | resolve 5720 | resonate 5721 | resort 5722 | resound 5723 | resource 5724 | resow 5725 | respect 5726 | respell 5727 | respire 5728 | respite 5729 | respond 5730 | respray 5731 | rest 5732 | restaff 5733 | restart 5734 | restate 5735 | restitch 5736 | restock 5737 | restore 5738 | restrain 5739 | restrengthen 5740 | restrict 5741 | restring 5742 | restructure 5743 | restudy 5744 | restyle 5745 | resubmit 5746 | resubscribe 5747 | result 5748 | resume 5749 | resupply 5750 | resurface 5751 | resurrect 5752 | resurvey 5753 | resuscitate 5754 | retail 5755 | retain 5756 | retake 5757 | retaliate 5758 | retard 5759 | retch 5760 | reteach 5761 | retell 5762 | retest 5763 | rethink 5764 | retie 5765 | retire 5766 | retool 5767 | retort 5768 | retouch 5769 | retrace 5770 | retract 5771 | retrain 5772 | retreat 5773 | retrench 5774 | retrieve 5775 | retrofire 5776 | retrofit 5777 | retrograde 5778 | retrogress 5779 | retrospect 5780 | retry 5781 | return 5782 | retype 5783 | reunify 5784 | reunite 5785 | reupholster 5786 | reuse 5787 | rev 5788 | revalue 5789 | revamp 5790 | reveal 5791 | revel 5792 | revenge 5793 | reverberate 5794 | revere 5795 | reverence 5796 | reverse 5797 | revert 5798 | review 5799 | revile 5800 | revise 5801 | revisit 5802 | revitalize 5803 | revive 5804 | revivify 5805 | revoke 5806 | revolt 5807 | revolutionise 5808 | revolutionize 5809 | revolve 5810 | reward 5811 | rewarm 5812 | rewash 5813 | reweave 5814 | rewed 5815 | reweigh 5816 | rewind 5817 | rewire 5818 | reword 5819 | rework 5820 | rewrite 5821 | rezone 5822 | rhapsodize 5823 | rhyme 5824 | rib 5825 | ribbon 5826 | rice 5827 | rick 5828 | ricochet 5829 | rid 5830 | riddle 5831 | ride 5832 | ridge 5833 | ridicule 5834 | riff 5835 | riffle 5836 | rifle 5837 | rift 5838 | rig 5839 | right 5840 | rightsize 5841 | rile 5842 | rim 5843 | rime 5844 | rinse 5845 | riot 5846 | rip 5847 | ripen 5848 | ripost 5849 | riposte 5850 | ripple 5851 | ripsaw 5852 | rise 5853 | risk 5854 | rival 5855 | rive 5856 | rivet 5857 | roach 5858 | roadblock 5859 | roam 5860 | roar 5861 | roast 5862 | rob 5863 | robe 5864 | robotize 5865 | rock 5866 | rocket 5867 | rod 5868 | rodeo 5869 | roger 5870 | rogue 5871 | roil 5872 | roister 5873 | roll 5874 | rollick 5875 | romance 5876 | romanticize 5877 | romp 5878 | roof 5879 | rook 5880 | room 5881 | roost 5882 | root 5883 | rope 5884 | rose 5885 | rosin 5886 | rot 5887 | rotate 5888 | rouge 5889 | rough 5890 | roughen 5891 | roughhouse 5892 | roughneck 5893 | roulette 5894 | round 5895 | rouse 5896 | roust 5897 | rout 5898 | route 5899 | routinize 5900 | rove 5901 | row 5902 | rowel 5903 | rub 5904 | rubber 5905 | rubberize 5906 | rubberneck 5907 | rue 5908 | ruff 5909 | ruffle 5910 | ruin 5911 | rule 5912 | rumba 5913 | rumble 5914 | ruminate 5915 | rummage 5916 | rumor 5917 | rumour 5918 | rumple 5919 | run 5920 | rupture 5921 | rush 5922 | rust 5923 | rusticate 5924 | rustle 5925 | rustproof 5926 | rut 5927 | saber 5928 | sabotage 5929 | sabre 5930 | sack 5931 | sacrifice 5932 | sadden 5933 | saddle 5934 | safari 5935 | safeguard 5936 | sag 5937 | sail 5938 | sailplane 5939 | saint 5940 | salaam 5941 | salivate 5942 | sallow 5943 | sally 5944 | salsa 5945 | salt 5946 | salute 5947 | salvage 5948 | salve 5949 | salvo 5950 | samba 5951 | sample 5952 | sanctify 5953 | sanction 5954 | sand 5955 | sandal 5956 | sandbag 5957 | sandblast 5958 | sandpaper 5959 | sandwich 5960 | sanitize 5961 | sap 5962 | sash 5963 | sashay 5964 | sass 5965 | sate 5966 | satiate 5967 | satirize 5968 | satisfy 5969 | saturate 5970 | sauce 5971 | sauna 5972 | saunter 5973 | saute 5974 | savage 5975 | save 5976 | savor 5977 | savour 5978 | savvy 5979 | saw 5980 | say 5981 | scab 5982 | scabbard 5983 | scaffold 5984 | scald 5985 | scale 5986 | scallop 5987 | scalp 5988 | scam 5989 | scamp 5990 | scamper 5991 | scan 5992 | scandal 5993 | scandalize 5994 | scant 5995 | scapegoat 5996 | scar 5997 | scare 5998 | scarf 5999 | scarify 6000 | scarp 6001 | scat 6002 | scatter 6003 | scavenge 6004 | scent 6005 | scepter 6006 | sceptre 6007 | schedule 6008 | scheme 6009 | schlep 6010 | schlepp 6011 | schmooze 6012 | school 6013 | schoolmaster 6014 | schuss 6015 | scintillate 6016 | scissor 6017 | scoff 6018 | scold 6019 | scollop 6020 | sconce 6021 | scoop 6022 | scoot 6023 | scope 6024 | scorch 6025 | score 6026 | scorn 6027 | scotch 6028 | scour 6029 | scourge 6030 | scout 6031 | scow 6032 | scowl 6033 | scrabble 6034 | scrag 6035 | scram 6036 | scramble 6037 | scrap 6038 | scrape 6039 | scratch 6040 | scrawl 6041 | scream 6042 | screech 6043 | screen 6044 | screw 6045 | scribble 6046 | scribe 6047 | scrimmage 6048 | scrimp 6049 | scrimshaw 6050 | script 6051 | scroll 6052 | scrooge 6053 | scrounge 6054 | scrub 6055 | scrunch 6056 | scruple 6057 | scrutinize 6058 | scuba 6059 | scud 6060 | scuff 6061 | scuffle 6062 | scull 6063 | sculpt 6064 | sculpture 6065 | scum 6066 | scupper 6067 | scurry 6068 | scuttle 6069 | scythe 6070 | seal 6071 | seam 6072 | sear 6073 | search 6074 | season 6075 | seat 6076 | secede 6077 | seclude 6078 | second 6079 | secrete 6080 | section 6081 | sector 6082 | secularize 6083 | secure 6084 | sedate 6085 | sediment 6086 | seduce 6087 | see 6088 | seed 6089 | seek 6090 | seem 6091 | seep 6092 | seesaw 6093 | seethe 6094 | segment 6095 | segregate 6096 | segue 6097 | seine 6098 | seize 6099 | select 6100 | self 6101 | sell 6102 | semaphore 6103 | send 6104 | sensationalize 6105 | sense 6106 | sensitize 6107 | sentence 6108 | sentimentalize 6109 | sentinel 6110 | separate 6111 | sepulcher 6112 | sepulchre 6113 | sequence 6114 | sequester 6115 | sequestrate 6116 | serenade 6117 | serge 6118 | serialize 6119 | sermonize 6120 | serpentine 6121 | serrate 6122 | serve 6123 | service 6124 | servo 6125 | set 6126 | settle 6127 | sever 6128 | sew 6129 | sewer 6130 | sex 6131 | shack 6132 | shackle 6133 | shade 6134 | shadow 6135 | shadowbox 6136 | shaft 6137 | shag 6138 | shake 6139 | shall 6140 | shallow 6141 | sham 6142 | shamble 6143 | shame 6144 | shammy 6145 | shampoo 6146 | shanghai 6147 | shank 6148 | shanty 6149 | shape 6150 | share 6151 | sharecrop 6152 | sharp 6153 | sharpen 6154 | shatter 6155 | shave 6156 | sheaf 6157 | shear 6158 | sheath 6159 | sheathe 6160 | sheave 6161 | shed 6162 | sheen 6163 | sheer 6164 | sheet 6165 | shelf 6166 | shell 6167 | shellac 6168 | shellack 6169 | shelter 6170 | shelve 6171 | shepherd 6172 | shew 6173 | shield 6174 | shift 6175 | shill 6176 | shim 6177 | shimmer 6178 | shimmy 6179 | shin 6180 | shine 6181 | shingle 6182 | shinny 6183 | ship 6184 | shipwreck 6185 | shirk 6186 | shirr 6187 | shit 6188 | shiver 6189 | shlep 6190 | shlepp 6191 | shoal 6192 | shock 6193 | shoe 6194 | shoehorn 6195 | shoo 6196 | shoot 6197 | shop 6198 | shoplift 6199 | shore 6200 | short 6201 | shortchange 6202 | shorten 6203 | shortwave 6204 | shot 6205 | shotgun 6206 | shoulder 6207 | shout 6208 | shove 6209 | shovel 6210 | show 6211 | showboat 6212 | showcase 6213 | shower 6214 | shred 6215 | shriek 6216 | shrill 6217 | shrimp 6218 | shrine 6219 | shrink 6220 | shrive 6221 | shrivel 6222 | shroud 6223 | shrug 6224 | shuck 6225 | shudder 6226 | shuffle 6227 | shun 6228 | shunt 6229 | shush 6230 | shut 6231 | shutter 6232 | shuttle 6233 | shuttlecock 6234 | shy 6235 | sic 6236 | sick 6237 | sicken 6238 | sickly 6239 | side 6240 | sideline 6241 | sidestep 6242 | sidestroke 6243 | sideswipe 6244 | sidetrack 6245 | sidle 6246 | siege 6247 | sieve 6248 | sift 6249 | sigh 6250 | sight 6251 | sightread 6252 | sign 6253 | signal 6254 | signalize 6255 | signet 6256 | signify 6257 | signpost 6258 | silence 6259 | silhouette 6260 | silk 6261 | silkscreen 6262 | silo 6263 | silt 6264 | silver 6265 | simmer 6266 | simonize 6267 | simper 6268 | simplify 6269 | simulate 6270 | simulcast 6271 | sin 6272 | sinew 6273 | sing 6274 | singe 6275 | single 6276 | sink 6277 | sip 6278 | siphon 6279 | sire 6280 | sirup 6281 | sit 6282 | site 6283 | situate 6284 | size 6285 | sizzle 6286 | skate 6287 | skateboard 6288 | skedaddle 6289 | sketch 6290 | skew 6291 | skewer 6292 | ski 6293 | skid 6294 | skill 6295 | skim 6296 | skimp 6297 | skin 6298 | skip 6299 | skipper 6300 | skirmish 6301 | skirt 6302 | skitter 6303 | skivvy 6304 | skoal 6305 | skulk 6306 | skunk 6307 | sky 6308 | skydive 6309 | skyjack 6310 | skylark 6311 | skyline 6312 | skyrocket 6313 | slab 6314 | slack 6315 | slacken 6316 | slag 6317 | slake 6318 | slalom 6319 | slam 6320 | slander 6321 | slang 6322 | slant 6323 | slap 6324 | slash 6325 | slat 6326 | slate 6327 | slather 6328 | slaughter 6329 | slave 6330 | slaver 6331 | slay 6332 | sled 6333 | sledge 6334 | sledgehammer 6335 | sleek 6336 | sleep 6337 | sleepwalk 6338 | sleet 6339 | sleeve 6340 | sleigh 6341 | slenderize 6342 | sleuth 6343 | slew 6344 | slice 6345 | slick 6346 | slide 6347 | slight 6348 | slim 6349 | slime 6350 | sling 6351 | slink 6352 | slip 6353 | slipcover 6354 | slipper 6355 | slipstream 6356 | slit 6357 | slither 6358 | sliver 6359 | slobber 6360 | slog 6361 | slop 6362 | slope 6363 | slosh 6364 | slot 6365 | slouch 6366 | slough 6367 | slow 6368 | slue 6369 | slug 6370 | sluice 6371 | slum 6372 | slumber 6373 | slump 6374 | slur 6375 | slurp 6376 | slurry 6377 | slush 6378 | smack 6379 | smart 6380 | smarten 6381 | smash 6382 | smear 6383 | smell 6384 | smelt 6385 | smile 6386 | smirch 6387 | smirk 6388 | smite 6389 | smith 6390 | smock 6391 | smoke 6392 | smolder 6393 | smooch 6394 | smooth 6395 | smother 6396 | smoulder 6397 | smudge 6398 | smuggle 6399 | smut 6400 | snack 6401 | snaffle 6402 | snafu 6403 | snag 6404 | snake 6405 | snap 6406 | snapshot 6407 | snare 6408 | snarl 6409 | snatch 6410 | sneak 6411 | sneer 6412 | sneeze 6413 | snicker 6414 | sniff 6415 | sniffle 6416 | snigger 6417 | snip 6418 | snipe 6419 | snitch 6420 | snivel 6421 | snood 6422 | snooker 6423 | snoop 6424 | snoot 6425 | snooze 6426 | snore 6427 | snorkel 6428 | snort 6429 | snow 6430 | snowball 6431 | snowboard 6432 | snowmobile 6433 | snowplow 6434 | snowshoe 6435 | snub 6436 | snuff 6437 | snuffle 6438 | snug 6439 | snuggle 6440 | soak 6441 | soap 6442 | soar 6443 | sob 6444 | sober 6445 | socialize 6446 | sock 6447 | socket 6448 | sod 6449 | sodden 6450 | sodomize 6451 | soften 6452 | soil 6453 | sojourn 6454 | solace 6455 | solder 6456 | soldier 6457 | sole 6458 | solemnify 6459 | solemnize 6460 | solicit 6461 | solidify 6462 | soliloquize 6463 | solo 6464 | solve 6465 | somersault 6466 | somerset 6467 | sonnet 6468 | soot 6469 | soothe 6470 | sop 6471 | sophisticate 6472 | sorrow 6473 | sort 6474 | sortie 6475 | sough 6476 | sound 6477 | soundproof 6478 | soup 6479 | sour 6480 | source 6481 | souse 6482 | south 6483 | sow 6484 | space 6485 | spacewalk 6486 | spade 6487 | span 6488 | spangle 6489 | spank 6490 | spar 6491 | spare 6492 | spark 6493 | sparkle 6494 | spat 6495 | spatter 6496 | spawn 6497 | spay 6498 | speak 6499 | spear 6500 | spearfish 6501 | spearhead 6502 | spec 6503 | specialize 6504 | specify 6505 | speck 6506 | speckle 6507 | speculate 6508 | speed 6509 | spell 6510 | spellbind 6511 | spend 6512 | spew 6513 | sphere 6514 | spice 6515 | spiderweb 6516 | spiel 6517 | spike 6518 | spill 6519 | spin 6520 | spindle 6521 | spiral 6522 | spire 6523 | spirit 6524 | spit 6525 | spite 6526 | splash 6527 | splat 6528 | splatter 6529 | splay 6530 | splice 6531 | splint 6532 | splinter 6533 | split 6534 | splotch 6535 | splurge 6536 | splutter 6537 | spoil 6538 | spoke 6539 | sponge 6540 | sponsor 6541 | spoof 6542 | spook 6543 | spool 6544 | spoon 6545 | spoor 6546 | spore 6547 | sport 6548 | spot 6549 | spotlight 6550 | spouse 6551 | spout 6552 | sprain 6553 | sprawl 6554 | spray 6555 | spread 6556 | sprig 6557 | spring 6558 | sprinkle 6559 | sprint 6560 | spritz 6561 | sprout 6562 | spruce 6563 | spud 6564 | spume 6565 | spur 6566 | spurn 6567 | spurt 6568 | sputter 6569 | spy 6570 | squabble 6571 | squadron 6572 | squall 6573 | squander 6574 | square 6575 | squash 6576 | squat 6577 | squawk 6578 | squeak 6579 | squeal 6580 | squeegee 6581 | squeeze 6582 | squelch 6583 | squib 6584 | squiggle 6585 | squint 6586 | squire 6587 | squirm 6588 | squirrel 6589 | squirt 6590 | squish 6591 | stab 6592 | stabilize 6593 | stable 6594 | stack 6595 | staff 6596 | stag 6597 | stage 6598 | stagger 6599 | stagnate 6600 | stain 6601 | stake 6602 | stale 6603 | stalemate 6604 | stalk 6605 | stall 6606 | stammer 6607 | stamp 6608 | stampede 6609 | stanch 6610 | stanchion 6611 | stand 6612 | standardize 6613 | staple 6614 | star 6615 | starboard 6616 | starch 6617 | stare 6618 | stargaze 6619 | start 6620 | startle 6621 | starve 6622 | stash 6623 | state 6624 | statement 6625 | station 6626 | statue 6627 | staunch 6628 | stave 6629 | stay 6630 | stead 6631 | steady 6632 | steal 6633 | steam 6634 | steamer 6635 | steamroll 6636 | steamroller 6637 | steel 6638 | steep 6639 | steepen 6640 | steeplechase 6641 | steer 6642 | stem 6643 | stencil 6644 | step 6645 | stereo 6646 | stereotype 6647 | sterilize 6648 | stet 6649 | stevedore 6650 | stew 6651 | steward 6652 | stick 6653 | sticker 6654 | stiff 6655 | stiffen 6656 | stifle 6657 | stigmatize 6658 | stiletto 6659 | still 6660 | stilt 6661 | stimulate 6662 | sting 6663 | stink 6664 | stint 6665 | stipple 6666 | stipulate 6667 | stir 6668 | stitch 6669 | stock 6670 | stockade 6671 | stockpile 6672 | stoke 6673 | stomach 6674 | stomp 6675 | stone 6676 | stonewall 6677 | stooge 6678 | stool 6679 | stoop 6680 | stop 6681 | stopper 6682 | stopple 6683 | store 6684 | storm 6685 | story 6686 | stove 6687 | stow 6688 | straddle 6689 | strafe 6690 | straggle 6691 | straighten 6692 | straightjacket 6693 | strain 6694 | straiten 6695 | straitjacket 6696 | strand 6697 | strangle 6698 | strangulate 6699 | strap 6700 | stratify 6701 | stray 6702 | streak 6703 | stream 6704 | streamline 6705 | strengthen 6706 | stress 6707 | stretch 6708 | stretcher 6709 | strew 6710 | stride 6711 | strike 6712 | string 6713 | strip 6714 | stripe 6715 | striptease 6716 | strive 6717 | stroke 6718 | stroll 6719 | strop 6720 | structure 6721 | struggle 6722 | strum 6723 | strut 6724 | stub 6725 | stucco 6726 | stud 6727 | study 6728 | stuff 6729 | stultify 6730 | stumble 6731 | stump 6732 | stun 6733 | stunt 6734 | stupefy 6735 | stutter 6736 | sty 6737 | style 6738 | stylize 6739 | stymie 6740 | stymy 6741 | sub 6742 | subcontract 6743 | subculture 6744 | subdivide 6745 | subdue 6746 | subject 6747 | subjoin 6748 | subjugate 6749 | sublease 6750 | sublet 6751 | sublimate 6752 | sublime 6753 | submarine 6754 | submerge 6755 | submerse 6756 | submit 6757 | subordinate 6758 | suborn 6759 | subpena 6760 | subpoena 6761 | subscribe 6762 | subside 6763 | subsidize 6764 | subsist 6765 | substantiate 6766 | substitute 6767 | subsume 6768 | subtitle 6769 | subtotal 6770 | subtract 6771 | subvert 6772 | subway 6773 | succeed 6774 | succor 6775 | succour 6776 | succumb 6777 | suck 6778 | sucker 6779 | suckle 6780 | suction 6781 | suds 6782 | sue 6783 | suede 6784 | suffer 6785 | suffice 6786 | suffix 6787 | suffocate 6788 | suffuse 6789 | sugar 6790 | sugarcoat 6791 | suggest 6792 | suicide 6793 | suit 6794 | sulfate 6795 | sulfur 6796 | sulk 6797 | sully 6798 | sulphur 6799 | sum 6800 | summarize 6801 | summer 6802 | summit 6803 | summon 6804 | summons 6805 | sun 6806 | sunbathe 6807 | sunburn 6808 | sunder 6809 | sundown 6810 | suntan 6811 | sup 6812 | superannuate 6813 | supercharge 6814 | superimpose 6815 | superintend 6816 | superpose 6817 | supersaturate 6818 | superscribe 6819 | supersede 6820 | supervene 6821 | supervise 6822 | supper 6823 | supplant 6824 | supple 6825 | supplement 6826 | supplicate 6827 | supply 6828 | support 6829 | suppose 6830 | suppress 6831 | suppurate 6832 | surcease 6833 | surcharge 6834 | surf 6835 | surface 6836 | surfboard 6837 | surfeit 6838 | surge 6839 | surmise 6840 | surmount 6841 | surname 6842 | surpass 6843 | surplus 6844 | surprise 6845 | surrender 6846 | surrogate 6847 | surround 6848 | surtax 6849 | survey 6850 | survive 6851 | suspect 6852 | suspend 6853 | suspicion 6854 | sustain 6855 | suture 6856 | swab 6857 | swaddle 6858 | swag 6859 | swagger 6860 | swallow 6861 | swamp 6862 | swan 6863 | swank 6864 | swap 6865 | sward 6866 | swarm 6867 | swash 6868 | swat 6869 | swathe 6870 | sway 6871 | swear 6872 | sweat 6873 | sweep 6874 | sweeten 6875 | swell 6876 | swelter 6877 | swerve 6878 | swig 6879 | swill 6880 | swim 6881 | swindle 6882 | swing 6883 | swipe 6884 | swirl 6885 | swish 6886 | switch 6887 | switchback 6888 | swivel 6889 | swob 6890 | swoon 6891 | swoop 6892 | swoosh 6893 | swop 6894 | syllabicate 6895 | syllabify 6896 | syllable 6897 | symbol 6898 | symbolize 6899 | sympathize 6900 | synapse 6901 | sync 6902 | synch 6903 | synchronize 6904 | syncopate 6905 | syndicate 6906 | synthesize 6907 | syphon 6908 | syringe 6909 | syrup 6910 | systematize 6911 | tab 6912 | tabby 6913 | tabernacle 6914 | table 6915 | tablet 6916 | taboo 6917 | tabor 6918 | tabu 6919 | tabulate 6920 | tack 6921 | tackle 6922 | tag 6923 | tail 6924 | tailgate 6925 | tailor 6926 | taint 6927 | take 6928 | talc 6929 | talk 6930 | tallow 6931 | tally 6932 | tallyho 6933 | tame 6934 | tamp 6935 | tamper 6936 | tampon 6937 | tan 6938 | tang 6939 | tangle 6940 | tango 6941 | tank 6942 | tantalise 6943 | tantalize 6944 | tap 6945 | tape 6946 | taper 6947 | tapestry 6948 | tar 6949 | tare 6950 | target 6951 | tariff 6952 | tarmac 6953 | tarnish 6954 | tarry 6955 | task 6956 | tassel 6957 | taste 6958 | tat 6959 | tatter 6960 | tattle 6961 | tattoo 6962 | taunt 6963 | tauten 6964 | tax 6965 | taxi 6966 | teach 6967 | team 6968 | teargas 6969 | tease 6970 | teasel 6971 | tee 6972 | teem 6973 | teeter 6974 | teethe 6975 | teetotal 6976 | telecast 6977 | telecommute 6978 | teleconference 6979 | telegram 6980 | telegraph 6981 | telemeter 6982 | telephone 6983 | telescope 6984 | televise 6985 | telex 6986 | tell 6987 | temp 6988 | temper 6989 | tempest 6990 | temporize 6991 | tempt 6992 | tenant 6993 | tend 6994 | tender 6995 | tenderize 6996 | tenon 6997 | tense 6998 | tension 6999 | tent 7000 | tenure 7001 | term 7002 | terminate 7003 | terrace 7004 | terrify 7005 | terrorize 7006 | tessellate 7007 | test 7008 | testify 7009 | tether 7010 | texture 7011 | thank 7012 | thatch 7013 | thaw 7014 | theme 7015 | theorize 7016 | thermostat 7017 | thicken 7018 | thieve 7019 | thin 7020 | think 7021 | thirst 7022 | thole 7023 | thorn 7024 | thou 7025 | thrall 7026 | thrash 7027 | thread 7028 | threat 7029 | threaten 7030 | thresh 7031 | thrill 7032 | thrive 7033 | throat 7034 | throb 7035 | throne 7036 | throng 7037 | throttle 7038 | throw 7039 | thrum 7040 | thrust 7041 | thud 7042 | thumb 7043 | thumbtack 7044 | thump 7045 | thunder 7046 | thwack 7047 | thwart 7048 | tick 7049 | ticket 7050 | tickle 7051 | ticktock 7052 | tide 7053 | tidy 7054 | tie 7055 | tier 7056 | tiff 7057 | tighten 7058 | tightrope 7059 | tile 7060 | till 7061 | tiller 7062 | tilt 7063 | timber 7064 | time 7065 | timetable 7066 | tin 7067 | tincture 7068 | ting 7069 | tinge 7070 | tingle 7071 | tinker 7072 | tinkle 7073 | tinsel 7074 | tint 7075 | tip 7076 | tipple 7077 | tiptoe 7078 | tire 7079 | tissue 7080 | tithe 7081 | titillate 7082 | titivate 7083 | title 7084 | titter 7085 | tittivate 7086 | toady 7087 | toast 7088 | toboggan 7089 | toddle 7090 | toe 7091 | toenail 7092 | tog 7093 | toggle 7094 | toil 7095 | toilet 7096 | toke 7097 | token 7098 | tole 7099 | tolerate 7100 | toll 7101 | tom 7102 | tomahawk 7103 | tomb 7104 | tomcat 7105 | tone 7106 | tong 7107 | tongue 7108 | tonsure 7109 | tool 7110 | toot 7111 | tooth 7112 | tootle 7113 | top 7114 | topple 7115 | topsoil 7116 | torch 7117 | torment 7118 | torpedo 7119 | torque 7120 | torture 7121 | toss 7122 | tot 7123 | total 7124 | tote 7125 | totter 7126 | touch 7127 | toughen 7128 | tour 7129 | tourney 7130 | tousle 7131 | tout 7132 | tow 7133 | towel 7134 | tower 7135 | toy 7136 | trace 7137 | track 7138 | trade 7139 | trademark 7140 | traduce 7141 | traffic 7142 | trail 7143 | train 7144 | traipse 7145 | tram 7146 | trammel 7147 | tramp 7148 | trample 7149 | trampoline 7150 | trance 7151 | tranquilize 7152 | tranquillize 7153 | transact 7154 | transcend 7155 | transcribe 7156 | transect 7157 | transfer 7158 | transfigure 7159 | transfix 7160 | transform 7161 | transfuse 7162 | transgress 7163 | transistorize 7164 | transit 7165 | transition 7166 | translate 7167 | transliterate 7168 | transmigrate 7169 | transmit 7170 | transmogrify 7171 | transmute 7172 | transpire 7173 | transplant 7174 | transport 7175 | transpose 7176 | transship 7177 | trap 7178 | trash 7179 | traumatize 7180 | travail 7181 | travel 7182 | traverse 7183 | travesty 7184 | trawl 7185 | tread 7186 | treadle 7187 | treasure 7188 | treat 7189 | treble 7190 | tree 7191 | trek 7192 | trellis 7193 | tremble 7194 | trench 7195 | trend 7196 | trespass 7197 | tress 7198 | triage 7199 | trial 7200 | triangulate 7201 | trice 7202 | trick 7203 | trickle 7204 | trifle 7205 | trig 7206 | trigger 7207 | trill 7208 | trim 7209 | trinket 7210 | trip 7211 | triple 7212 | triplicate 7213 | trisect 7214 | triumph 7215 | trivialize 7216 | troll 7217 | trolley 7218 | trolly 7219 | tromp 7220 | troop 7221 | trot 7222 | trouble 7223 | troubleshoot 7224 | trounce 7225 | troupe 7226 | trow 7227 | trowel 7228 | truant 7229 | truce 7230 | truck 7231 | truckle 7232 | trudge 7233 | true 7234 | trump 7235 | trumpet 7236 | truncate 7237 | truncheon 7238 | trundle 7239 | truss 7240 | trust 7241 | trustee 7242 | try 7243 | tryst 7244 | tub 7245 | tube 7246 | tuck 7247 | tucker 7248 | tuft 7249 | tug 7250 | tumble 7251 | tun 7252 | tune 7253 | tunnel 7254 | turbocharge 7255 | turf 7256 | turn 7257 | turpentine 7258 | turtle 7259 | tusk 7260 | tussle 7261 | tut 7262 | tutor 7263 | twaddle 7264 | twang 7265 | tweak 7266 | tweet 7267 | twiddle 7268 | twig 7269 | twill 7270 | twin 7271 | twine 7272 | twinge 7273 | twinkle 7274 | twirl 7275 | twist 7276 | twit 7277 | twitch 7278 | twitter 7279 | type 7280 | typecast 7281 | typeset 7282 | typewrite 7283 | typify 7284 | tyrannize 7285 | tyre 7286 | ulcerate 7287 | ululate 7288 | umber 7289 | umlaut 7290 | ump 7291 | umpire 7292 | unbar 7293 | unbend 7294 | unbind 7295 | unblock 7296 | unbolt 7297 | unbosom 7298 | unbuckle 7299 | unburden 7300 | unbutton 7301 | uncap 7302 | unchain 7303 | unclasp 7304 | uncloak 7305 | unclog 7306 | unclothe 7307 | uncoil 7308 | uncork 7309 | uncouple 7310 | uncover 7311 | uncross 7312 | uncurl 7313 | undeceive 7314 | underachieve 7315 | underact 7316 | underbid 7317 | undercharge 7318 | undercoat 7319 | undercut 7320 | underestimate 7321 | underexpose 7322 | underfeed 7323 | undergo 7324 | underlay 7325 | underlie 7326 | underline 7327 | undermine 7328 | underpay 7329 | underpin 7330 | underplay 7331 | underrate 7332 | underscore 7333 | undersell 7334 | undershoot 7335 | undersign 7336 | understand 7337 | understate 7338 | understudy 7339 | undertake 7340 | undervalue 7341 | underwhelm 7342 | underwrite 7343 | undo 7344 | undress 7345 | undulate 7346 | unearth 7347 | unfasten 7348 | unfetter 7349 | unfit 7350 | unfix 7351 | unfold 7352 | unfreeze 7353 | unfrock 7354 | unfurl 7355 | unhand 7356 | unharness 7357 | unhinge 7358 | unhitch 7359 | unhook 7360 | unhorse 7361 | unicycle 7362 | uniform 7363 | unify 7364 | unionize 7365 | unite 7366 | unitize 7367 | universalize 7368 | unlace 7369 | unlatch 7370 | unlearn 7371 | unleash 7372 | unlimber 7373 | unload 7374 | unlock 7375 | unloose 7376 | unloosen 7377 | unmake 7378 | unman 7379 | unmask 7380 | unnerve 7381 | unpack 7382 | unpin 7383 | unplug 7384 | unquote 7385 | unravel 7386 | unreel 7387 | unroll 7388 | unsaddle 7389 | unsay 7390 | unscramble 7391 | unscrew 7392 | unseal 7393 | unseat 7394 | unsettle 7395 | unshackle 7396 | unsheathe 7397 | unsnap 7398 | unsnarl 7399 | unsteady 7400 | unstop 7401 | unstrap 7402 | untangle 7403 | untidy 7404 | untie 7405 | untwist 7406 | unveil 7407 | unwind 7408 | unwrap 7409 | unyoke 7410 | unzip 7411 | up 7412 | upbraid 7413 | upchuck 7414 | update 7415 | upend 7416 | upgrade 7417 | uphold 7418 | upholster 7419 | uplift 7420 | upload 7421 | uppercase 7422 | uppercut 7423 | upraise 7424 | uprear 7425 | upright 7426 | uproot 7427 | upscale 7428 | upset 7429 | upstage 7430 | upstart 7431 | upsurge 7432 | upswing 7433 | upthrust 7434 | upturn 7435 | urbanize 7436 | urge 7437 | urinate 7438 | use 7439 | usher 7440 | usurp 7441 | utilize 7442 | utter 7443 | vacate 7444 | vacation 7445 | vaccinate 7446 | vacillate 7447 | vacuum 7448 | valet 7449 | validate 7450 | valuate 7451 | value 7452 | valve 7453 | vamoose 7454 | vamp 7455 | van 7456 | vandalise 7457 | vandalize 7458 | vanish 7459 | vanquish 7460 | vapor 7461 | vaporise 7462 | vaporize 7463 | vapour 7464 | variegate 7465 | varnish 7466 | vary 7467 | vat 7468 | vault 7469 | vaunt 7470 | vector 7471 | veer 7472 | veg 7473 | vegetate 7474 | veil 7475 | vein 7476 | vend 7477 | veneer 7478 | venerate 7479 | venom 7480 | vent 7481 | ventilate 7482 | venture 7483 | verbalize 7484 | verge 7485 | verify 7486 | vermilion 7487 | verse 7488 | versify 7489 | vesiculate 7490 | vest 7491 | vestibule 7492 | vet 7493 | veto 7494 | vex 7495 | vial 7496 | vibrate 7497 | vice 7498 | victimize 7499 | victual 7500 | video 7501 | videotape 7502 | vie 7503 | view 7504 | vignette 7505 | vilify 7506 | vindicate 7507 | vinegar 7508 | vintage 7509 | violate 7510 | visa 7511 | vise 7512 | vision 7513 | visit 7514 | visor 7515 | visualize 7516 | vitalize 7517 | vitiate 7518 | vitrify 7519 | vitriol 7520 | vituperate 7521 | vivify 7522 | vivisect 7523 | vizor 7524 | vocalize 7525 | vociferate 7526 | voice 7527 | void 7528 | volatilize 7529 | volley 7530 | volunteer 7531 | vomit 7532 | voodoo 7533 | vote 7534 | vouch 7535 | voucher 7536 | vouchsafe 7537 | vow 7538 | vowel 7539 | voyage 7540 | vulcanize 7541 | vulgarize 7542 | wad 7543 | waddle 7544 | wade 7545 | wafer 7546 | waffle 7547 | waft 7548 | wag 7549 | wage 7550 | wager 7551 | waggle 7552 | waggon 7553 | wagon 7554 | wail 7555 | wainscot 7556 | wait 7557 | waiter 7558 | waitress 7559 | waive 7560 | wake 7561 | waken 7562 | wale 7563 | walk 7564 | wall 7565 | wallop 7566 | wallow 7567 | wallpaper 7568 | waltz 7569 | wan 7570 | wander 7571 | wane 7572 | wangle 7573 | want 7574 | wanton 7575 | war 7576 | warble 7577 | ward 7578 | wardrobe 7579 | ware 7580 | warehouse 7581 | warm 7582 | warn 7583 | warp 7584 | warrant 7585 | warranty 7586 | wash 7587 | wassail 7588 | waste 7589 | watch 7590 | watchdog 7591 | water 7592 | watermark 7593 | waterproof 7594 | wattle 7595 | wave 7596 | waver 7597 | waylay 7598 | weaken 7599 | wean 7600 | weapon 7601 | wear 7602 | weary 7603 | weasel 7604 | weather 7605 | weatherize 7606 | weatherproof 7607 | weatherstrip 7608 | web 7609 | wed 7610 | wedge 7611 | wee 7612 | weed 7613 | weekend 7614 | ween 7615 | weep 7616 | weigh 7617 | weight 7618 | welch 7619 | welcome 7620 | weld 7621 | well 7622 | welsh 7623 | welt 7624 | welter 7625 | wench 7626 | wend 7627 | westernize 7628 | wet 7629 | whack 7630 | whale 7631 | wham 7632 | wharf 7633 | wheedle 7634 | wheel 7635 | wheelbarrow 7636 | wheeze 7637 | whelm 7638 | whelp 7639 | wherry 7640 | whet 7641 | whiff 7642 | while 7643 | whimper 7644 | whine 7645 | whinny 7646 | whip 7647 | whiplash 7648 | whipsaw 7649 | whir 7650 | whirl 7651 | whirr 7652 | whisk 7653 | whisper 7654 | whist 7655 | whistle 7656 | white 7657 | whiten 7658 | whitewash 7659 | whittle 7660 | whiz 7661 | whizz 7662 | whoa 7663 | wholesale 7664 | whoop 7665 | whoosh 7666 | whore 7667 | wick 7668 | widen 7669 | widow 7670 | wield 7671 | wife 7672 | wig 7673 | wiggle 7674 | wigwag 7675 | wildcat 7676 | wile 7677 | will 7678 | willow 7679 | wilt 7680 | wimple 7681 | win 7682 | wince 7683 | winch 7684 | windlass 7685 | windmill 7686 | window 7687 | windrow 7688 | windsurf 7689 | wine 7690 | wing 7691 | wink 7692 | winkle 7693 | winnow 7694 | winter 7695 | winterize 7696 | wipe 7697 | wire 7698 | wireless 7699 | wiretap 7700 | wise 7701 | wisecrack 7702 | wish 7703 | wisp 7704 | @wit 7705 | witch 7706 | withdraw 7707 | withe 7708 | wither 7709 | withhold 7710 | withstand 7711 | witness 7712 | wive 7713 | wobble 7714 | wolf 7715 | woman 7716 | womanize 7717 | won 7718 | wonder 7719 | wont 7720 | woo 7721 | wood 7722 | woodshed 7723 | woof 7724 | word 7725 | work 7726 | worm 7727 | worry 7728 | worsen 7729 | worship 7730 | worst 7731 | worth 7732 | wound 7733 | wow 7734 | wrack 7735 | wrangle 7736 | wrap 7737 | wreak 7738 | wreath 7739 | wreathe 7740 | wreck 7741 | wrench 7742 | wrest 7743 | wrestle 7744 | wriggle 7745 | wring 7746 | wrinkle 7747 | write 7748 | writhe 7749 | wrong 7750 | xerox 7751 | yacht 7752 | yack 7753 | yak 7754 | yammer 7755 | yank 7756 | yap 7757 | yard 7758 | yarn 7759 | yaw 7760 | yawl 7761 | yawn 7762 | yearn 7763 | yeast 7764 | yell 7765 | yellow 7766 | yelp 7767 | yen 7768 | yes 7769 | yield 7770 | yip 7771 | yodel 7772 | yoke 7773 | yowl 7774 | yuck 7775 | yuk 7776 | zap 7777 | zero 7778 | zest 7779 | zigzag 7780 | zinc 7781 | zing 7782 | zip 7783 | zipper 7784 | zone 7785 | zoom --------------------------------------------------------------------------------