├── example.png ├── pyproject.toml ├── LICENSE ├── ipython_profile.py ├── README.md ├── .gitignore └── poetry.lock /example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sevazhidkov/ipython-profile/HEAD/example.png -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "ipython-profile" 3 | version = "0.1.0" 4 | description = "An opinionated iPython profile for interactive development" 5 | authors = ["Seva Zhidkov "] 6 | license = "MIT License" 7 | 8 | [tool.poetry.scripts] 9 | ipython-profile = 'ipython_profile:run' 10 | 11 | [tool.poetry.dependencies] 12 | python = ">=3.8,<4.0" 13 | click = "^8.0.3" 14 | ipython = "^8.0.1" 15 | ipython-autoimport = "^0.3" 16 | requests = "^2.27.1" 17 | 18 | [tool.poetry.dev-dependencies] 19 | 20 | [build-system] 21 | requires = ["poetry-core>=1.0.0"] 22 | build-backend = "poetry.core.masonry.api" 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2022 Seva Zhidkov 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /ipython_profile.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path, PurePath 2 | import subprocess 3 | import click 4 | 5 | _INIT_FILES = { 6 | PurePath('ipython_config.py'): ( 7 | """ 8 | ## lines of code to run at IPython startup. 9 | # Default: [] 10 | c.InteractiveShellApp.exec_lines = [ 11 | '%autoreload 2' 12 | ] 13 | 14 | ## A list of dotted module names of IPython extensions to load. 15 | # Default: [] 16 | c.InteractiveShellApp.extensions = ['autoreload', 'ipython_autoimport'] 17 | """ 18 | ) 19 | } 20 | 21 | 22 | def _echo(text): 23 | click.echo(f'[ipython-profile] {text}') 24 | 25 | 26 | @click.command() 27 | @click.option('--profile-dir', 28 | default='./.ipython-profile', help='Path to created') 29 | def run(profile_dir): 30 | profile_dir = Path(profile_dir) 31 | if profile_dir.is_file(): 32 | _echo('--profile-dir can\'t be a file.') 33 | return 34 | 35 | if not profile_dir.exists(): 36 | profile_dir.mkdir() 37 | for filename, content in _INIT_FILES.items(): 38 | (profile_dir / filename).write_text(content) 39 | _echo('Created .ipython-profile directory with default config.') 40 | 41 | project_directory = profile_dir.parent 42 | git_related = ( 43 | (project_directory / PurePath('.git')).exists() or 44 | (project_directory / PurePath('.gitignore')).exists() 45 | ) 46 | if git_related: 47 | _echo( 48 | 'It seems that you are using git in this project. ' 49 | 'Consider adding .ipython-profile to .gitignore.' 50 | ) 51 | 52 | subprocess.call(['ipython', '--profile-dir', str(profile_dir)]) 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ipython-profile 2 | 3 | A slightly opinionated template for iPython configuration for interactive development. 4 | **Auto-reload** and **no imports** for packages and modules in the project. 5 | 6 | ![Example usage](example.png) 7 | 8 | ## Usage 9 | 10 | Install the library using your favorite package manager: 11 | ```bash 12 | # With poetry 13 | poetry add ipython-profile 14 | 15 | # With pip 16 | pip install ipython-profile 17 | ``` 18 | 19 | Now you can use `ipython-profile` in the project directory: 20 | ```bash 21 | $ cd ~/awesome-project 22 | $ ipython-profile # If installed with pip 23 | $ poetry run ipython-profile # If installed locally with poetry 24 | [ipython-profile] Created .ipython-profile directory with default config. 25 | [ipython-profile] It seems that you are using git in this project. Consider adding .ipython-profile to .gitignore. 26 | Python 3.9.6 (default, Jun 29 2021, 05:25:02) 27 | Type 'copyright', 'credits' or 'license' for more information 28 | IPython 8.0.1 -- An enhanced Interactive Python. Type '?' for help. 29 | 30 | IPython profile: .ipython-profile 31 | 32 | In [1]: 33 | ``` 34 | 35 | It loads modules automatically (magic!) if the called name wasn't found in the environment using [ipython-autoimport](https://github.com/anntzer/ipython-autoimport). 36 | 37 | It also automatically reloads modules on changes using [iPython autoreload extension](https://ipython.readthedocs.io/en/stable/config/extensions/autoreload.html). 38 | 39 | ```python 40 | In [1]: requests.get('https://google.com/') 41 | Autoimport: import requests 42 | Out[1]: 43 | 44 | In [2]: libs.auth.get_token() 45 | Autoimport: import libs 46 | Autoimport: import libs.auth 47 | Out[2]: 1 48 | 49 | In [3]: # I'm changing libs/auth.py 50 | 51 | In [4]: libs.auth.get_token() 52 | Out[4]: 2 53 | ``` 54 | 55 | `ipython-profile` by default creates an iPython profile directory in `./.ipython-profile`. 56 | If you want to set a different directory, use `--profile-dir` option. 57 | 58 | ## How it works? 59 | 60 | The template is small and straightforward underneath: it installs `ipython-autoimport` and creates this iPython configuration file: 61 | ```python 62 | ## lines of code to run at IPython startup. 63 | # Default: [] 64 | c.InteractiveShellApp.exec_lines = [ 65 | '%autoreload 2' 66 | ] 67 | 68 | ## A list of dotted module names of IPython extensions to load. 69 | # Default: [] 70 | c.InteractiveShellApp.extensions = ['autoreload', 'ipython_autoimport'] 71 | ``` 72 | 73 | Basically, it enables auto-import and auto-reload for all modules. 74 | 75 | In the future the profile might include some tools to simplify using it with web frameworks (Django, FastAPI) and testing frameworks. 76 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 105 | __pypackages__/ 106 | 107 | # Celery stuff 108 | celerybeat-schedule 109 | celerybeat.pid 110 | 111 | # SageMath parsed files 112 | *.sage.py 113 | 114 | # Environments 115 | .env 116 | .venv 117 | env/ 118 | venv/ 119 | ENV/ 120 | env.bak/ 121 | venv.bak/ 122 | 123 | # Spyder project settings 124 | .spyderproject 125 | .spyproject 126 | 127 | # Rope project settings 128 | .ropeproject 129 | 130 | # mkdocs documentation 131 | /site 132 | 133 | # mypy 134 | .mypy_cache/ 135 | .dmypy.json 136 | dmypy.json 137 | 138 | # Pyre type checker 139 | .pyre/ 140 | 141 | # pytype static type analyzer 142 | .pytype/ 143 | 144 | # Cython debug symbols 145 | cython_debug/ 146 | 147 | # PyCharm 148 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 149 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 150 | # and can be added to the global gitignore or merged into this file. For a more nuclear 151 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 152 | .idea/ 153 | 154 | .ipython-profile 155 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "appnope" 3 | version = "0.1.2" 4 | description = "Disable App Nap on macOS >= 10.9" 5 | category = "main" 6 | optional = false 7 | python-versions = "*" 8 | 9 | [[package]] 10 | name = "asttokens" 11 | version = "2.0.5" 12 | description = "Annotate AST trees with source code positions" 13 | category = "main" 14 | optional = false 15 | python-versions = "*" 16 | 17 | [package.dependencies] 18 | six = "*" 19 | 20 | [package.extras] 21 | test = ["astroid", "pytest"] 22 | 23 | [[package]] 24 | name = "backcall" 25 | version = "0.2.0" 26 | description = "Specifications for callback functions passed in to an API" 27 | category = "main" 28 | optional = false 29 | python-versions = "*" 30 | 31 | [[package]] 32 | name = "black" 33 | version = "22.1.0" 34 | description = "The uncompromising code formatter." 35 | category = "main" 36 | optional = false 37 | python-versions = ">=3.6.2" 38 | 39 | [package.dependencies] 40 | click = ">=8.0.0" 41 | mypy-extensions = ">=0.4.3" 42 | pathspec = ">=0.9.0" 43 | platformdirs = ">=2" 44 | tomli = ">=1.1.0" 45 | typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} 46 | 47 | [package.extras] 48 | colorama = ["colorama (>=0.4.3)"] 49 | d = ["aiohttp (>=3.7.4)"] 50 | jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] 51 | uvloop = ["uvloop (>=0.15.2)"] 52 | 53 | [[package]] 54 | name = "certifi" 55 | version = "2021.10.8" 56 | description = "Python package for providing Mozilla's CA Bundle." 57 | category = "main" 58 | optional = false 59 | python-versions = "*" 60 | 61 | [[package]] 62 | name = "charset-normalizer" 63 | version = "2.0.12" 64 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 65 | category = "main" 66 | optional = false 67 | python-versions = ">=3.5.0" 68 | 69 | [package.extras] 70 | unicode_backport = ["unicodedata2"] 71 | 72 | [[package]] 73 | name = "click" 74 | version = "8.0.3" 75 | description = "Composable command line interface toolkit" 76 | category = "main" 77 | optional = false 78 | python-versions = ">=3.6" 79 | 80 | [package.dependencies] 81 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 82 | 83 | [[package]] 84 | name = "colorama" 85 | version = "0.4.4" 86 | description = "Cross-platform colored terminal text." 87 | category = "main" 88 | optional = false 89 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 90 | 91 | [[package]] 92 | name = "decorator" 93 | version = "5.1.1" 94 | description = "Decorators for Humans" 95 | category = "main" 96 | optional = false 97 | python-versions = ">=3.5" 98 | 99 | [[package]] 100 | name = "executing" 101 | version = "0.8.2" 102 | description = "Get the currently executing AST node of a frame, and other information" 103 | category = "main" 104 | optional = false 105 | python-versions = "*" 106 | 107 | [[package]] 108 | name = "idna" 109 | version = "3.3" 110 | description = "Internationalized Domain Names in Applications (IDNA)" 111 | category = "main" 112 | optional = false 113 | python-versions = ">=3.5" 114 | 115 | [[package]] 116 | name = "ipython" 117 | version = "8.0.1" 118 | description = "IPython: Productive Interactive Computing" 119 | category = "main" 120 | optional = false 121 | python-versions = ">=3.8" 122 | 123 | [package.dependencies] 124 | appnope = {version = "*", markers = "sys_platform == \"darwin\""} 125 | backcall = "*" 126 | black = "*" 127 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 128 | decorator = "*" 129 | jedi = ">=0.16" 130 | matplotlib-inline = "*" 131 | pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} 132 | pickleshare = "*" 133 | prompt-toolkit = ">=2.0.0,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.1.0" 134 | pygments = "*" 135 | stack-data = "*" 136 | traitlets = ">=5" 137 | 138 | [package.extras] 139 | all = ["Sphinx (>=1.3)", "curio", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.19)", "pandas", "pygments", "pytest", "pytest-asyncio", "qtconsole", "testpath", "trio"] 140 | doc = ["Sphinx (>=1.3)"] 141 | kernel = ["ipykernel"] 142 | nbconvert = ["nbconvert"] 143 | nbformat = ["nbformat"] 144 | notebook = ["notebook", "ipywidgets"] 145 | parallel = ["ipyparallel"] 146 | qtconsole = ["qtconsole"] 147 | test = ["pytest", "pytest-asyncio", "testpath", "pygments"] 148 | test_extra = ["pytest", "testpath", "curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.19)", "pandas", "pygments", "trio"] 149 | 150 | [[package]] 151 | name = "ipython-autoimport" 152 | version = "0.3" 153 | description = "Automagically import missing modules in IPython." 154 | category = "main" 155 | optional = false 156 | python-versions = ">=3" 157 | 158 | [package.dependencies] 159 | ipython = ">=4.0" 160 | setuptools-scm = "*" 161 | 162 | [[package]] 163 | name = "jedi" 164 | version = "0.18.1" 165 | description = "An autocompletion tool for Python that can be used for text editors." 166 | category = "main" 167 | optional = false 168 | python-versions = ">=3.6" 169 | 170 | [package.dependencies] 171 | parso = ">=0.8.0,<0.9.0" 172 | 173 | [package.extras] 174 | qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] 175 | testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<7.0.0)"] 176 | 177 | [[package]] 178 | name = "matplotlib-inline" 179 | version = "0.1.3" 180 | description = "Inline Matplotlib backend for Jupyter" 181 | category = "main" 182 | optional = false 183 | python-versions = ">=3.5" 184 | 185 | [package.dependencies] 186 | traitlets = "*" 187 | 188 | [[package]] 189 | name = "mypy-extensions" 190 | version = "0.4.3" 191 | description = "Experimental type system extensions for programs checked with the mypy typechecker." 192 | category = "main" 193 | optional = false 194 | python-versions = "*" 195 | 196 | [[package]] 197 | name = "packaging" 198 | version = "21.3" 199 | description = "Core utilities for Python packages" 200 | category = "main" 201 | optional = false 202 | python-versions = ">=3.6" 203 | 204 | [package.dependencies] 205 | pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" 206 | 207 | [[package]] 208 | name = "parso" 209 | version = "0.8.3" 210 | description = "A Python Parser" 211 | category = "main" 212 | optional = false 213 | python-versions = ">=3.6" 214 | 215 | [package.extras] 216 | qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] 217 | testing = ["docopt", "pytest (<6.0.0)"] 218 | 219 | [[package]] 220 | name = "pathspec" 221 | version = "0.9.0" 222 | description = "Utility library for gitignore style pattern matching of file paths." 223 | category = "main" 224 | optional = false 225 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" 226 | 227 | [[package]] 228 | name = "pexpect" 229 | version = "4.8.0" 230 | description = "Pexpect allows easy control of interactive console applications." 231 | category = "main" 232 | optional = false 233 | python-versions = "*" 234 | 235 | [package.dependencies] 236 | ptyprocess = ">=0.5" 237 | 238 | [[package]] 239 | name = "pickleshare" 240 | version = "0.7.5" 241 | description = "Tiny 'shelve'-like database with concurrency support" 242 | category = "main" 243 | optional = false 244 | python-versions = "*" 245 | 246 | [[package]] 247 | name = "platformdirs" 248 | version = "2.5.0" 249 | description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." 250 | category = "main" 251 | optional = false 252 | python-versions = ">=3.7" 253 | 254 | [package.extras] 255 | docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] 256 | test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] 257 | 258 | [[package]] 259 | name = "prompt-toolkit" 260 | version = "3.0.28" 261 | description = "Library for building powerful interactive command lines in Python" 262 | category = "main" 263 | optional = false 264 | python-versions = ">=3.6.2" 265 | 266 | [package.dependencies] 267 | wcwidth = "*" 268 | 269 | [[package]] 270 | name = "ptyprocess" 271 | version = "0.7.0" 272 | description = "Run a subprocess in a pseudo terminal" 273 | category = "main" 274 | optional = false 275 | python-versions = "*" 276 | 277 | [[package]] 278 | name = "pure-eval" 279 | version = "0.2.2" 280 | description = "Safely evaluate AST nodes without side effects" 281 | category = "main" 282 | optional = false 283 | python-versions = "*" 284 | 285 | [package.extras] 286 | tests = ["pytest"] 287 | 288 | [[package]] 289 | name = "pygments" 290 | version = "2.11.2" 291 | description = "Pygments is a syntax highlighting package written in Python." 292 | category = "main" 293 | optional = false 294 | python-versions = ">=3.5" 295 | 296 | [[package]] 297 | name = "pyparsing" 298 | version = "3.0.7" 299 | description = "Python parsing module" 300 | category = "main" 301 | optional = false 302 | python-versions = ">=3.6" 303 | 304 | [package.extras] 305 | diagrams = ["jinja2", "railroad-diagrams"] 306 | 307 | [[package]] 308 | name = "requests" 309 | version = "2.27.1" 310 | description = "Python HTTP for Humans." 311 | category = "main" 312 | optional = false 313 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" 314 | 315 | [package.dependencies] 316 | certifi = ">=2017.4.17" 317 | charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""} 318 | idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""} 319 | urllib3 = ">=1.21.1,<1.27" 320 | 321 | [package.extras] 322 | socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] 323 | use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] 324 | 325 | [[package]] 326 | name = "setuptools-scm" 327 | version = "6.4.2" 328 | description = "the blessed package to manage your versions by scm tags" 329 | category = "main" 330 | optional = false 331 | python-versions = ">=3.6" 332 | 333 | [package.dependencies] 334 | packaging = ">=20.0" 335 | tomli = ">=1.0.0" 336 | 337 | [package.extras] 338 | test = ["pytest (>=6.2)", "virtualenv (>20)"] 339 | toml = ["setuptools (>=42)"] 340 | 341 | [[package]] 342 | name = "six" 343 | version = "1.16.0" 344 | description = "Python 2 and 3 compatibility utilities" 345 | category = "main" 346 | optional = false 347 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 348 | 349 | [[package]] 350 | name = "stack-data" 351 | version = "0.1.4" 352 | description = "Extract data from python stack frames and tracebacks for informative displays" 353 | category = "main" 354 | optional = false 355 | python-versions = "*" 356 | 357 | [package.dependencies] 358 | asttokens = "*" 359 | executing = "*" 360 | pure-eval = "*" 361 | 362 | [package.extras] 363 | tests = ["pytest", "typeguard", "pygments", "littleutils"] 364 | 365 | [[package]] 366 | name = "tomli" 367 | version = "2.0.1" 368 | description = "A lil' TOML parser" 369 | category = "main" 370 | optional = false 371 | python-versions = ">=3.7" 372 | 373 | [[package]] 374 | name = "traitlets" 375 | version = "5.1.1" 376 | description = "Traitlets Python configuration system" 377 | category = "main" 378 | optional = false 379 | python-versions = ">=3.7" 380 | 381 | [package.extras] 382 | test = ["pytest"] 383 | 384 | [[package]] 385 | name = "typing-extensions" 386 | version = "4.1.0" 387 | description = "Backported and Experimental Type Hints for Python 3.6+" 388 | category = "main" 389 | optional = false 390 | python-versions = ">=3.6" 391 | 392 | [[package]] 393 | name = "urllib3" 394 | version = "1.26.8" 395 | description = "HTTP library with thread-safe connection pooling, file post, and more." 396 | category = "main" 397 | optional = false 398 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" 399 | 400 | [package.extras] 401 | brotli = ["brotlipy (>=0.6.0)"] 402 | secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] 403 | socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] 404 | 405 | [[package]] 406 | name = "wcwidth" 407 | version = "0.2.5" 408 | description = "Measures the displayed width of unicode strings in a terminal" 409 | category = "main" 410 | optional = false 411 | python-versions = "*" 412 | 413 | [metadata] 414 | lock-version = "1.1" 415 | python-versions = ">=3.8,<4.0" 416 | content-hash = "a8662f283ccc610f3d0b733490a3f3516ed9a38fca7068e0dd1c5c36820f70b8" 417 | 418 | [metadata.files] 419 | appnope = [ 420 | {file = "appnope-0.1.2-py2.py3-none-any.whl", hash = "sha256:93aa393e9d6c54c5cd570ccadd8edad61ea0c4b9ea7a01409020c9aa019eb442"}, 421 | {file = "appnope-0.1.2.tar.gz", hash = "sha256:dd83cd4b5b460958838f6eb3000c660b1f9caf2a5b1de4264e941512f603258a"}, 422 | ] 423 | asttokens = [ 424 | {file = "asttokens-2.0.5-py2.py3-none-any.whl", hash = "sha256:0844691e88552595a6f4a4281a9f7f79b8dd45ca4ccea82e5e05b4bbdb76705c"}, 425 | {file = "asttokens-2.0.5.tar.gz", hash = "sha256:9a54c114f02c7a9480d56550932546a3f1fe71d8a02f1bc7ccd0ee3ee35cf4d5"}, 426 | ] 427 | backcall = [ 428 | {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, 429 | {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, 430 | ] 431 | black = [ 432 | {file = "black-22.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1297c63b9e1b96a3d0da2d85d11cd9bf8664251fd69ddac068b98dc4f34f73b6"}, 433 | {file = "black-22.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2ff96450d3ad9ea499fc4c60e425a1439c2120cbbc1ab959ff20f7c76ec7e866"}, 434 | {file = "black-22.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e21e1f1efa65a50e3960edd068b6ae6d64ad6235bd8bfea116a03b21836af71"}, 435 | {file = "black-22.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2f69158a7d120fd641d1fa9a921d898e20d52e44a74a6fbbcc570a62a6bc8ab"}, 436 | {file = "black-22.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:228b5ae2c8e3d6227e4bde5920d2fc66cc3400fde7bcc74f480cb07ef0b570d5"}, 437 | {file = "black-22.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b1a5ed73ab4c482208d20434f700d514f66ffe2840f63a6252ecc43a9bc77e8a"}, 438 | {file = "black-22.1.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35944b7100af4a985abfcaa860b06af15590deb1f392f06c8683b4381e8eeaf0"}, 439 | {file = "black-22.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:7835fee5238fc0a0baf6c9268fb816b5f5cd9b8793423a75e8cd663c48d073ba"}, 440 | {file = "black-22.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dae63f2dbf82882fa3b2a3c49c32bffe144970a573cd68d247af6560fc493ae1"}, 441 | {file = "black-22.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fa1db02410b1924b6749c245ab38d30621564e658297484952f3d8a39fce7e8"}, 442 | {file = "black-22.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c8226f50b8c34a14608b848dc23a46e5d08397d009446353dad45e04af0c8e28"}, 443 | {file = "black-22.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2d6f331c02f0f40aa51a22e479c8209d37fcd520c77721c034517d44eecf5912"}, 444 | {file = "black-22.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:742ce9af3086e5bd07e58c8feb09dbb2b047b7f566eb5f5bc63fd455814979f3"}, 445 | {file = "black-22.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fdb8754b453fb15fad3f72cd9cad3e16776f0964d67cf30ebcbf10327a3777a3"}, 446 | {file = "black-22.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5660feab44c2e3cb24b2419b998846cbb01c23c7fe645fee45087efa3da2d61"}, 447 | {file = "black-22.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:6f2f01381f91c1efb1451998bd65a129b3ed6f64f79663a55fe0e9b74a5f81fd"}, 448 | {file = "black-22.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:efbadd9b52c060a8fc3b9658744091cb33c31f830b3f074422ed27bad2b18e8f"}, 449 | {file = "black-22.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8871fcb4b447206904932b54b567923e5be802b9b19b744fdff092bd2f3118d0"}, 450 | {file = "black-22.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ccad888050f5393f0d6029deea2a33e5ae371fd182a697313bdbd835d3edaf9c"}, 451 | {file = "black-22.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07e5c049442d7ca1a2fc273c79d1aecbbf1bc858f62e8184abe1ad175c4f7cc2"}, 452 | {file = "black-22.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:373922fc66676133ddc3e754e4509196a8c392fec3f5ca4486673e685a421321"}, 453 | {file = "black-22.1.0-py3-none-any.whl", hash = "sha256:3524739d76b6b3ed1132422bf9d82123cd1705086723bc3e235ca39fd21c667d"}, 454 | {file = "black-22.1.0.tar.gz", hash = "sha256:a7c0192d35635f6fc1174be575cb7915e92e5dd629ee79fdaf0dcfa41a80afb5"}, 455 | ] 456 | certifi = [ 457 | {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, 458 | {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, 459 | ] 460 | charset-normalizer = [ 461 | {file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"}, 462 | {file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"}, 463 | ] 464 | click = [ 465 | {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"}, 466 | {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"}, 467 | ] 468 | colorama = [ 469 | {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, 470 | {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, 471 | ] 472 | decorator = [ 473 | {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, 474 | {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, 475 | ] 476 | executing = [ 477 | {file = "executing-0.8.2-py2.py3-none-any.whl", hash = "sha256:32fc6077b103bd19e6494a72682d66d5763cf20a106d5aa7c5ccbea4e47b0df7"}, 478 | {file = "executing-0.8.2.tar.gz", hash = "sha256:c23bf42e9a7b9b212f185b1b2c3c91feb895963378887bb10e64a2e612ec0023"}, 479 | ] 480 | idna = [ 481 | {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, 482 | {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, 483 | ] 484 | ipython = [ 485 | {file = "ipython-8.0.1-py3-none-any.whl", hash = "sha256:c503a0dd6ccac9c8c260b211f2dd4479c042b49636b097cc9a0d55fe62dff64c"}, 486 | {file = "ipython-8.0.1.tar.gz", hash = "sha256:ab564d4521ea8ceaac26c3a2c6e5ddbca15c8848fd5a5cc325f960da88d42974"}, 487 | ] 488 | ipython-autoimport = [ 489 | {file = "ipython_autoimport-0.3-py3-none-any.whl", hash = "sha256:6b5a4fb3f0dec728a0a695fe9f74195fc2f343d21436f18a4e79484edae8910d"}, 490 | ] 491 | jedi = [ 492 | {file = "jedi-0.18.1-py2.py3-none-any.whl", hash = "sha256:637c9635fcf47945ceb91cd7f320234a7be540ded6f3e99a50cb6febdfd1ba8d"}, 493 | {file = "jedi-0.18.1.tar.gz", hash = "sha256:74137626a64a99c8eb6ae5832d99b3bdd7d29a3850fe2aa80a4126b2a7d949ab"}, 494 | ] 495 | matplotlib-inline = [ 496 | {file = "matplotlib-inline-0.1.3.tar.gz", hash = "sha256:a04bfba22e0d1395479f866853ec1ee28eea1485c1d69a6faf00dc3e24ff34ee"}, 497 | {file = "matplotlib_inline-0.1.3-py3-none-any.whl", hash = "sha256:aed605ba3b72462d64d475a21a9296f400a19c4f74a31b59103d2a99ffd5aa5c"}, 498 | ] 499 | mypy-extensions = [ 500 | {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, 501 | {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, 502 | ] 503 | packaging = [ 504 | {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, 505 | {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, 506 | ] 507 | parso = [ 508 | {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"}, 509 | {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"}, 510 | ] 511 | pathspec = [ 512 | {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, 513 | {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, 514 | ] 515 | pexpect = [ 516 | {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, 517 | {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, 518 | ] 519 | pickleshare = [ 520 | {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, 521 | {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, 522 | ] 523 | platformdirs = [ 524 | {file = "platformdirs-2.5.0-py3-none-any.whl", hash = "sha256:30671902352e97b1eafd74ade8e4a694782bd3471685e78c32d0fdfd3aa7e7bb"}, 525 | {file = "platformdirs-2.5.0.tar.gz", hash = "sha256:8ec11dfba28ecc0715eb5fb0147a87b1bf325f349f3da9aab2cd6b50b96b692b"}, 526 | ] 527 | prompt-toolkit = [ 528 | {file = "prompt_toolkit-3.0.28-py3-none-any.whl", hash = "sha256:30129d870dcb0b3b6a53efdc9d0a83ea96162ffd28ffe077e94215b233dc670c"}, 529 | {file = "prompt_toolkit-3.0.28.tar.gz", hash = "sha256:9f1cd16b1e86c2968f2519d7fb31dd9d669916f515612c269d14e9ed52b51650"}, 530 | ] 531 | ptyprocess = [ 532 | {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, 533 | {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, 534 | ] 535 | pure-eval = [ 536 | {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, 537 | {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, 538 | ] 539 | pygments = [ 540 | {file = "Pygments-2.11.2-py3-none-any.whl", hash = "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65"}, 541 | {file = "Pygments-2.11.2.tar.gz", hash = "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a"}, 542 | ] 543 | pyparsing = [ 544 | {file = "pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"}, 545 | {file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"}, 546 | ] 547 | requests = [ 548 | {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"}, 549 | {file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"}, 550 | ] 551 | setuptools-scm = [ 552 | {file = "setuptools_scm-6.4.2-py3-none-any.whl", hash = "sha256:acea13255093849de7ccb11af9e1fb8bde7067783450cee9ef7a93139bddf6d4"}, 553 | {file = "setuptools_scm-6.4.2.tar.gz", hash = "sha256:6833ac65c6ed9711a4d5d2266f8024cfa07c533a0e55f4c12f6eff280a5a9e30"}, 554 | ] 555 | six = [ 556 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, 557 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, 558 | ] 559 | stack-data = [ 560 | {file = "stack_data-0.1.4-py3-none-any.whl", hash = "sha256:02cc0683cbc445ae4ca8c4e3a0e58cb1df59f252efb0aa016b34804a707cf9bc"}, 561 | {file = "stack_data-0.1.4.tar.gz", hash = "sha256:7769ed2482ce0030e00175dd1bf4ef1e873603b6ab61cd3da443b410e64e9477"}, 562 | ] 563 | tomli = [ 564 | {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, 565 | {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, 566 | ] 567 | traitlets = [ 568 | {file = "traitlets-5.1.1-py3-none-any.whl", hash = "sha256:2d313cc50a42cd6c277e7d7dc8d4d7fedd06a2c215f78766ae7b1a66277e0033"}, 569 | {file = "traitlets-5.1.1.tar.gz", hash = "sha256:059f456c5a7c1c82b98c2e8c799f39c9b8128f6d0d46941ee118daace9eb70c7"}, 570 | ] 571 | typing-extensions = [ 572 | {file = "typing_extensions-4.1.0-py3-none-any.whl", hash = "sha256:c13180fbaa7cd97065a4915ceba012bdb31dc34743e63ddee16360161d358414"}, 573 | {file = "typing_extensions-4.1.0.tar.gz", hash = "sha256:ba97c5143e5bb067b57793c726dd857b1671d4b02ced273ca0538e71ff009095"}, 574 | ] 575 | urllib3 = [ 576 | {file = "urllib3-1.26.8-py2.py3-none-any.whl", hash = "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed"}, 577 | {file = "urllib3-1.26.8.tar.gz", hash = "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"}, 578 | ] 579 | wcwidth = [ 580 | {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, 581 | {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, 582 | ] 583 | --------------------------------------------------------------------------------