Source code for pyutil.nvim_profiling
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Automate profiling nvim.
=============
Nvim Profiler
=============
.. module:: nvim_profiling
:synopsis: Automate the process of profiling neovim.
.. highlight:: ipython
Attaching to a remote instance from the REPL
============================================
The below code displays how to attach to a remote neovim instance.::
>>> if not os.environ.get('NVIM_LISTEN_ADDRESS'): # we have no running nvim
>>> subprocess.run(['nvim&']) # are we allowed to do this?
>>> import pynvim
>>> vim = pynvim.attach('socket', path=os.environ.get('NVIM_LISTEN_ADDRESS'))
>>> vim.command('edit $MYVIMRC')
>>> vim_root = vim.current.buffer
Finding the initialization file to profile
==========================================
Here's the help documentation on how to find an ``init.vim`` file assuming it's placed
in the standard location I.E. ``~/.config/nvim`` or :envvar:`USERPROFILE`\\AppData\\Local\\nvim.
.. code-block:: vim
stdpath({what}) *stdpath()* *E6100*
Returns |standard-path| locations of various default files and directories.
{what} Type Description ~
cache String Cache directory. Arbitrary temporary
storage for plugins, etc.
config String User configuration directory. The
|init.vim| is stored here.
config_dirs List Additional configuration directories.
data String User data directory. The |shada-file|
is stored here.
data_dirs List Additional data directories.
Example:
:echo stdpath("config")
Roadmap
========
In the future this module is going to move towards implementing a command
that will behave similarly to the following command run in the shell:
.. code-block:: shell-session
nvim --startuptime test.txt test.py test.txt -c"bn"
# Also we could make the base command
nvim --clean --startuptime foo.log example_module.py foo.log -c'bn'
-------------------------
"""
import argparse
import datetime
import logging
import os
from platform import system
from shutil import which
import subprocess
import sys
from typing import AnyStr
import pynvim
from pyutil.__about__ import __version__
from pyutil.env_checks import check_xdg_config_home
LOGGER = logging.getLogger(name=__name__)
LOG_LEVEL = "logging.WARNING"
[docs]def _parse_arguments():
"""Parse arguments given by the user."""
parser = argparse.ArgumentParser(
prog='Neovim Profiler', description='Automate profiling startuptime.')
parser.add_argument(
"-p",
"--path",
dest="path",
help="Path to the location of the temporary buffer for Nvim.")
parser.add_argument(
'-ll',
'--log_level',
dest='log_level',
metavar='Log Level.',
choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
help='Set the logging level')
parser.add_argument('-V',
'--version',
action='version',
version='%(prog)s' + __version__)
if len(sys.argv) == 1:
parser.print_help()
sys.exit()
else:
return parser.parse_args()
[docs]class Neovim:
"""Instantiate a connection to neovim if it's running, establish the path if not.
Got to the point where I thought:
*Let's just rewrite this module.*
"""
def __init__(self, exe=None):
if exe:
self.exe = exe
else:
self.exe = self._get_instance()
[docs] @property
def running_instance(self):
"""Is neovim running?"""
try:
remote = os.environ.get('NVIM_LISTEN_ADDRESS')
except OSError:
return None
else:
return remote
[docs] def _get_instance(self):
"""Determine if neovim is running."""
if self.running_instance:
vim = pynvim.attach('socket', path=self.running_instance)
return vim
else:
return None
@property
def _exe_path(self):
"""Where is neovim located?"""
return which('nvim')
def __repr__(self) -> str:
return f'<Nvim: {self.__class__.__name__}, {self.exe}>'
[docs]def output_results(output_dir):
"""Checks that an directory named profiling exists.
IPython has a function in :mod:`IPython.utils` that I believe is called
ensure_dir_exists. Do we provide anything that that implementation doesn't?
Parameters
----------
output_dir : str
Directory to store profiling results in.
Returns
-------
Bool
"""
if os.path.isdir(os.path.join(output_dir, 'profiling')) is False:
try:
os.mkdir(os.path.join(output_dir, 'profiling'))
except OSError as e:
sys.exit(e)
else:
return True
else:
return True
[docs]def main(nvim_root):
"""Profile nvim.
Parameters
-----------
nvim_root : str
The directory where nvim's configuration files are found.
Returns
--------
profiling_log_file : str
Creates file based on the current time in ISO format profiling nvim.
.. todo:: Allow the ``test.py`` file that we use for startup to be configured.
"""
now = datetime.date.isoformat(datetime.datetime.now())
if output_results(nvim_root):
now = 'profiling' + os.path.sep + str(now)
profiling_log_file = os.path.join(nvim_root, '', now)
subprocess.check_output([
'nvim', '--startuptime', profiling_log_file, 'test.py', '-c', ':qall'
])
if __name__ == "__main__":
from pdb import set_trace; set_trace()
user_args = _parse_arguments()
try:
LOG_LEVEL = user_args.log_level
except Exception as e:
LOGGER.error(e, exc_info=True)
nvim_root = None # Define it temporarily we need to refactor
# main(nvim_root)