mirror of
				https://github.com/nvbn/thefuck.git
				synced 2025-11-04 09:02:08 +00:00 
			
		
		
		
	Compare commits
	
		
			11 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					6c4333944f | ||
| 
						 | 
					31f5185642 | ||
| 
						 | 
					d71dbc5de4 | ||
| 
						 | 
					fabef80056 | ||
| 
						 | 
					b4c4fdf706 | ||
| 
						 | 
					d267488520 | ||
| 
						 | 
					e31124335f | ||
| 
						 | 
					71a5182b9a | ||
| 
						 | 
					6a096155dc | ||
| 
						 | 
					5742d2d910 | ||
| 
						 | 
					754bb3e21f | 
@@ -1 +1,2 @@
 | 
			
		||||
include LICENSE.md
 | 
			
		||||
include fastentrypoints.py
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										110
									
								
								fastentrypoints.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								fastentrypoints.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,110 @@
 | 
			
		||||
# Copyright (c) 2016, Aaron Christianson
 | 
			
		||||
# All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# Redistribution and use in source and binary forms, with or without
 | 
			
		||||
# modification, are permitted provided that the following conditions are
 | 
			
		||||
# met:
 | 
			
		||||
#
 | 
			
		||||
# 1. Redistributions of source code must retain the above copyright
 | 
			
		||||
#    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
#
 | 
			
		||||
# 2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
#    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
#    documentation and/or other materials provided with the distribution.
 | 
			
		||||
#
 | 
			
		||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 | 
			
		||||
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 | 
			
		||||
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 | 
			
		||||
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
			
		||||
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 | 
			
		||||
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 | 
			
		||||
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 | 
			
		||||
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 | 
			
		||||
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
'''
 | 
			
		||||
Monkey patch setuptools to write faster console_scripts with this format:
 | 
			
		||||
 | 
			
		||||
    import sys
 | 
			
		||||
    from mymodule import entry_function
 | 
			
		||||
    sys.exit(entry_function())
 | 
			
		||||
 | 
			
		||||
This is better.
 | 
			
		||||
 | 
			
		||||
(c) 2016, Aaron Christianson
 | 
			
		||||
http://github.com/ninjaaron/fast-entry_points
 | 
			
		||||
'''
 | 
			
		||||
from setuptools.command import easy_install
 | 
			
		||||
import re
 | 
			
		||||
TEMPLATE = '''\
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
# EASY-INSTALL-ENTRY-SCRIPT: '{3}','{4}','{5}'
 | 
			
		||||
__requires__ = '{3}'
 | 
			
		||||
import re
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
from {0} import {1}
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
 | 
			
		||||
    sys.exit({2}())'''
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@classmethod
 | 
			
		||||
def get_args(cls, dist, header=None):
 | 
			
		||||
    """
 | 
			
		||||
    Yield write_script() argument tuples for a distribution's
 | 
			
		||||
    console_scripts and gui_scripts entry points.
 | 
			
		||||
    """
 | 
			
		||||
    if header is None:
 | 
			
		||||
        header = cls.get_header()
 | 
			
		||||
    spec = str(dist.as_requirement())
 | 
			
		||||
    for type_ in 'console', 'gui':
 | 
			
		||||
        group = type_ + '_scripts'
 | 
			
		||||
        for name, ep in dist.get_entry_map(group).items():
 | 
			
		||||
            # ensure_safe_name
 | 
			
		||||
            if re.search(r'[\\/]', name):
 | 
			
		||||
                raise ValueError("Path separators not allowed in script names")
 | 
			
		||||
            script_text = TEMPLATE.format(
 | 
			
		||||
                          ep.module_name, ep.attrs[0], '.'.join(ep.attrs),
 | 
			
		||||
                          spec, group, name)
 | 
			
		||||
            args = cls._get_script_args(type_, name, header, script_text)
 | 
			
		||||
            for res in args:
 | 
			
		||||
                yield res
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
easy_install.ScriptWriter.get_args = get_args
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    import os
 | 
			
		||||
    import re
 | 
			
		||||
    import shutil
 | 
			
		||||
    import sys
 | 
			
		||||
    dests = sys.argv[1:] or ['.']
 | 
			
		||||
    filename = re.sub('\.pyc$', '.py', __file__)
 | 
			
		||||
 | 
			
		||||
    for dst in dests:
 | 
			
		||||
        shutil.copy(filename, dst)
 | 
			
		||||
        manifest_path = os.path.join(dst, 'MANIFEST.in')
 | 
			
		||||
        setup_path = os.path.join(dst, 'setup.py')
 | 
			
		||||
 | 
			
		||||
        # Insert the include statement to MANIFEST.in if not present
 | 
			
		||||
        with open(manifest_path, 'a+') as manifest:
 | 
			
		||||
            manifest.seek(0)
 | 
			
		||||
            manifest_content = manifest.read()
 | 
			
		||||
            if not 'include fastentrypoints.py' in manifest_content:
 | 
			
		||||
                manifest.write(('\n' if manifest_content else '')
 | 
			
		||||
                               + 'include fastentrypoints.py')
 | 
			
		||||
 | 
			
		||||
        # Insert the import statement to setup.py if not present
 | 
			
		||||
        with open(setup_path, 'a+') as setup:
 | 
			
		||||
            setup.seek(0)
 | 
			
		||||
            setup_content = setup.read()
 | 
			
		||||
            if not 'import fastentrypoints' in setup_content:
 | 
			
		||||
                setup.seek(0)
 | 
			
		||||
                setup.truncate()
 | 
			
		||||
                setup.write('import fastentrypoints\n' + setup_content)
 | 
			
		||||
 | 
			
		||||
print(__name__)
 | 
			
		||||
							
								
								
									
										4
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								setup.py
									
									
									
									
									
								
							@@ -3,6 +3,8 @@ from setuptools import setup, find_packages
 | 
			
		||||
import pkg_resources
 | 
			
		||||
import sys
 | 
			
		||||
import os
 | 
			
		||||
import fastentrypoints
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    if int(pkg_resources.get_distribution("pip").version.split('.')[0]) < 6:
 | 
			
		||||
@@ -29,7 +31,7 @@ elif (3, 0) < version < (3, 3):
 | 
			
		||||
          ' ({}.{} detected).'.format(*version))
 | 
			
		||||
    sys.exit(-1)
 | 
			
		||||
 | 
			
		||||
VERSION = '3.19'
 | 
			
		||||
VERSION = '3.21'
 | 
			
		||||
 | 
			
		||||
install_requires = ['psutil', 'colorama', 'six', 'decorator']
 | 
			
		||||
extras_require = {':python_version<"3.4"': ['pathlib2'],
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
import os
 | 
			
		||||
import pytest
 | 
			
		||||
from thefuck import shells
 | 
			
		||||
from thefuck import conf, const
 | 
			
		||||
@@ -56,7 +57,13 @@ def set_shell(monkeypatch, request):
 | 
			
		||||
    def _set(cls):
 | 
			
		||||
        shell = cls()
 | 
			
		||||
        monkeypatch.setattr('thefuck.shells.shell', shell)
 | 
			
		||||
        request.addfinalizer()
 | 
			
		||||
        return shell
 | 
			
		||||
 | 
			
		||||
    return _set
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture(autouse=True)
 | 
			
		||||
def os_environ(monkeypatch):
 | 
			
		||||
    env = {'PATH': os.environ['PATH']}
 | 
			
		||||
    monkeypatch.setattr('os.environ', env)
 | 
			
		||||
    return env
 | 
			
		||||
 
 | 
			
		||||
@@ -50,8 +50,8 @@ def test_match(command):
 | 
			
		||||
    assert match(command)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('command, new_command', [
 | 
			
		||||
@pytest.mark.parametrize('command, url', [
 | 
			
		||||
    (Command('yarn help clean', stdout=stdout_clean),
 | 
			
		||||
     open_command('https://yarnpkg.com/en/docs/cli/clean'))])
 | 
			
		||||
def test_get_new_command(command, new_command):
 | 
			
		||||
    assert get_new_command(command) == new_command
 | 
			
		||||
     'https://yarnpkg.com/en/docs/cli/clean')])
 | 
			
		||||
def test_get_new_command(command, url):
 | 
			
		||||
    assert get_new_command(command) == open_command(url)
 | 
			
		||||
 
 | 
			
		||||
@@ -18,17 +18,14 @@ class TestFish(object):
 | 
			
		||||
            b'man\nmath\npopd\npushd\nruby')
 | 
			
		||||
        return mock
 | 
			
		||||
 | 
			
		||||
    @pytest.fixture
 | 
			
		||||
    def os_environ(self, monkeypatch, key, value):
 | 
			
		||||
        monkeypatch.setattr('os.environ', {key: value})
 | 
			
		||||
 | 
			
		||||
    @pytest.mark.parametrize('key, value', [
 | 
			
		||||
        ('TF_OVERRIDDEN_ALIASES', 'cut,git,sed'),  # legacy
 | 
			
		||||
        ('THEFUCK_OVERRIDDEN_ALIASES', 'cut,git,sed'),
 | 
			
		||||
        ('THEFUCK_OVERRIDDEN_ALIASES', 'cut, git, sed'),
 | 
			
		||||
        ('THEFUCK_OVERRIDDEN_ALIASES', ' cut,\tgit,sed\n'),
 | 
			
		||||
        ('THEFUCK_OVERRIDDEN_ALIASES', '\ncut,\n\ngit,\tsed\r')])
 | 
			
		||||
    def test_get_overridden_aliases(self, shell, os_environ):
 | 
			
		||||
    def test_get_overridden_aliases(self, shell, os_environ, key, value):
 | 
			
		||||
        os_environ[key] = value
 | 
			
		||||
        assert shell._get_overridden_aliases() == {'cd', 'cut', 'git', 'grep',
 | 
			
		||||
                                                   'ls', 'man', 'open', 'sed'}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,14 +10,6 @@ def load_source(mocker):
 | 
			
		||||
    return mocker.patch('thefuck.conf.load_source')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def environ(monkeypatch):
 | 
			
		||||
    data = {}
 | 
			
		||||
    monkeypatch.setattr('thefuck.conf.os.environ', data)
 | 
			
		||||
    return data
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.usefixture('environ')
 | 
			
		||||
def test_settings_defaults(load_source, settings):
 | 
			
		||||
    load_source.return_value = object()
 | 
			
		||||
    settings.init()
 | 
			
		||||
@@ -25,7 +17,6 @@ def test_settings_defaults(load_source, settings):
 | 
			
		||||
        assert getattr(settings, key) == val
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.usefixture('environ')
 | 
			
		||||
class TestSettingsFromFile(object):
 | 
			
		||||
    def test_from_file(self, load_source, settings):
 | 
			
		||||
        load_source.return_value = Mock(rules=['test'],
 | 
			
		||||
@@ -54,15 +45,15 @@ class TestSettingsFromFile(object):
 | 
			
		||||
 | 
			
		||||
@pytest.mark.usefixture('load_source')
 | 
			
		||||
class TestSettingsFromEnv(object):
 | 
			
		||||
    def test_from_env(self, environ, settings):
 | 
			
		||||
        environ.update({'THEFUCK_RULES': 'bash:lisp',
 | 
			
		||||
                        'THEFUCK_EXCLUDE_RULES': 'git:vim',
 | 
			
		||||
                        'THEFUCK_WAIT_COMMAND': '55',
 | 
			
		||||
                        'THEFUCK_REQUIRE_CONFIRMATION': 'true',
 | 
			
		||||
                        'THEFUCK_NO_COLORS': 'false',
 | 
			
		||||
                        'THEFUCK_PRIORITY': 'bash=10:lisp=wrong:vim=15',
 | 
			
		||||
                        'THEFUCK_WAIT_SLOW_COMMAND': '999',
 | 
			
		||||
                        'THEFUCK_SLOW_COMMANDS': 'lein:react-native:./gradlew'})
 | 
			
		||||
    def test_from_env(self, os_environ, settings):
 | 
			
		||||
        os_environ.update({'THEFUCK_RULES': 'bash:lisp',
 | 
			
		||||
                           'THEFUCK_EXCLUDE_RULES': 'git:vim',
 | 
			
		||||
                           'THEFUCK_WAIT_COMMAND': '55',
 | 
			
		||||
                           'THEFUCK_REQUIRE_CONFIRMATION': 'true',
 | 
			
		||||
                           'THEFUCK_NO_COLORS': 'false',
 | 
			
		||||
                           'THEFUCK_PRIORITY': 'bash=10:lisp=wrong:vim=15',
 | 
			
		||||
                           'THEFUCK_WAIT_SLOW_COMMAND': '999',
 | 
			
		||||
                           'THEFUCK_SLOW_COMMANDS': 'lein:react-native:./gradlew'})
 | 
			
		||||
        settings.init()
 | 
			
		||||
        assert settings.rules == ['bash', 'lisp']
 | 
			
		||||
        assert settings.exclude_rules == ['git', 'vim']
 | 
			
		||||
@@ -73,8 +64,8 @@ class TestSettingsFromEnv(object):
 | 
			
		||||
        assert settings.wait_slow_command == 999
 | 
			
		||||
        assert settings.slow_commands == ['lein', 'react-native', './gradlew']
 | 
			
		||||
 | 
			
		||||
    def test_from_env_with_DEFAULT(self, environ, settings):
 | 
			
		||||
        environ.update({'THEFUCK_RULES': 'DEFAULT_RULES:bash:lisp'})
 | 
			
		||||
    def test_from_env_with_DEFAULT(self, os_environ, settings):
 | 
			
		||||
        os_environ.update({'THEFUCK_RULES': 'DEFAULT_RULES:bash:lisp'})
 | 
			
		||||
        settings.init()
 | 
			
		||||
        assert settings.rules == const.DEFAULT_RULES + ['bash', 'lisp']
 | 
			
		||||
 | 
			
		||||
@@ -116,15 +107,15 @@ class TestInitializeSettingsFile(object):
 | 
			
		||||
    (False, '/user/test/config/', '/user/test/config/thefuck'),
 | 
			
		||||
    (True, '~/.config', '~/.thefuck'),
 | 
			
		||||
    (True, '/user/test/config/', '~/.thefuck')])
 | 
			
		||||
def test_get_user_dir_path(mocker, environ, settings, legacy_dir_exists,
 | 
			
		||||
def test_get_user_dir_path(mocker, os_environ, settings, legacy_dir_exists,
 | 
			
		||||
                           xdg_config_home, result):
 | 
			
		||||
    mocker.patch('thefuck.conf.Path.is_dir',
 | 
			
		||||
                 return_value=legacy_dir_exists)
 | 
			
		||||
 | 
			
		||||
    if xdg_config_home is not None:
 | 
			
		||||
        environ['XDG_CONFIG_HOME'] = xdg_config_home
 | 
			
		||||
        os_environ['XDG_CONFIG_HOME'] = xdg_config_home
 | 
			
		||||
    else:
 | 
			
		||||
        environ.pop('XDG_CONFIG_HOME', None)
 | 
			
		||||
        os_environ.pop('XDG_CONFIG_HOME', None)
 | 
			
		||||
 | 
			
		||||
    path = settings._get_user_dir_path().as_posix()
 | 
			
		||||
    assert path == os.path.expanduser(result)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
import pytest
 | 
			
		||||
import json
 | 
			
		||||
from six import StringIO
 | 
			
		||||
from mock import MagicMock
 | 
			
		||||
from thefuck.shells.generic import ShellConfiguration
 | 
			
		||||
from thefuck.not_configured import main
 | 
			
		||||
@@ -11,19 +13,33 @@ def usage_tracker(mocker):
 | 
			
		||||
        new_callable=MagicMock)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _assert_tracker_updated(usage_tracker, pid):
 | 
			
		||||
@pytest.fixture(autouse=True)
 | 
			
		||||
def usage_tracker_io(usage_tracker):
 | 
			
		||||
    io = StringIO()
 | 
			
		||||
    usage_tracker.return_value \
 | 
			
		||||
        .open.return_value \
 | 
			
		||||
        .__enter__.return_value \
 | 
			
		||||
        .write.assert_called_once_with(str(pid))
 | 
			
		||||
                 .open.return_value \
 | 
			
		||||
                 .__enter__.return_value = io
 | 
			
		||||
    return io
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _change_tracker(usage_tracker, pid):
 | 
			
		||||
    usage_tracker.return_value.exists.return_value = True
 | 
			
		||||
@pytest.fixture(autouse=True)
 | 
			
		||||
def usage_tracker_exists(usage_tracker):
 | 
			
		||||
    usage_tracker.return_value \
 | 
			
		||||
        .open.return_value \
 | 
			
		||||
        .__enter__.return_value \
 | 
			
		||||
        .read.return_value = str(pid)
 | 
			
		||||
                 .exists.return_value = True
 | 
			
		||||
    return usage_tracker.return_value.exists
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _assert_tracker_updated(usage_tracker_io, pid):
 | 
			
		||||
    usage_tracker_io.seek(0)
 | 
			
		||||
    info = json.load(usage_tracker_io)
 | 
			
		||||
    assert info['pid'] == pid
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _change_tracker(usage_tracker_io, pid):
 | 
			
		||||
    usage_tracker_io.truncate(0)
 | 
			
		||||
    info = {'pid': pid, 'time': 0}
 | 
			
		||||
    json.dump(info, usage_tracker_io)
 | 
			
		||||
    usage_tracker_io.seek(0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture(autouse=True)
 | 
			
		||||
@@ -67,29 +83,28 @@ def test_for_generic_shell(shell, logs):
 | 
			
		||||
    logs.how_to_configure_alias.assert_called_once()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_on_first_run(usage_tracker, shell_pid, logs):
 | 
			
		||||
def test_on_first_run(usage_tracker_io, usage_tracker_exists, shell_pid, logs):
 | 
			
		||||
    shell_pid.return_value = 12
 | 
			
		||||
    usage_tracker.return_value.exists.return_value = False
 | 
			
		||||
    main()
 | 
			
		||||
    _assert_tracker_updated(usage_tracker, 12)
 | 
			
		||||
    usage_tracker_exists.return_value = False
 | 
			
		||||
    _assert_tracker_updated(usage_tracker_io, 12)
 | 
			
		||||
    logs.how_to_configure_alias.assert_called_once()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_on_run_after_other_commands(usage_tracker, shell_pid, shell, logs):
 | 
			
		||||
def test_on_run_after_other_commands(usage_tracker_io, shell_pid, shell, logs):
 | 
			
		||||
    shell_pid.return_value = 12
 | 
			
		||||
    shell.get_history.return_value = ['fuck', 'ls']
 | 
			
		||||
    _change_tracker(usage_tracker, 12)
 | 
			
		||||
    _change_tracker(usage_tracker_io, 12)
 | 
			
		||||
    main()
 | 
			
		||||
    logs.how_to_configure_alias.assert_called_once()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_on_first_run_from_current_shell(usage_tracker, shell_pid,
 | 
			
		||||
def test_on_first_run_from_current_shell(usage_tracker_io, shell_pid,
 | 
			
		||||
                                         shell, logs):
 | 
			
		||||
    shell.get_history.return_value = ['fuck']
 | 
			
		||||
    shell_pid.return_value = 12
 | 
			
		||||
    _change_tracker(usage_tracker, 55)
 | 
			
		||||
    main()
 | 
			
		||||
    _assert_tracker_updated(usage_tracker, 12)
 | 
			
		||||
    _assert_tracker_updated(usage_tracker_io, 12)
 | 
			
		||||
    logs.how_to_configure_alias.assert_called_once()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -104,21 +119,21 @@ def test_when_cant_configure_automatically(shell_pid, shell, logs):
 | 
			
		||||
    logs.how_to_configure_alias.assert_called_once()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_when_already_configured(usage_tracker, shell_pid,
 | 
			
		||||
def test_when_already_configured(usage_tracker_io, shell_pid,
 | 
			
		||||
                                 shell, shell_config, logs):
 | 
			
		||||
    shell.get_history.return_value = ['fuck']
 | 
			
		||||
    shell_pid.return_value = 12
 | 
			
		||||
    _change_tracker(usage_tracker, 12)
 | 
			
		||||
    _change_tracker(usage_tracker_io, 12)
 | 
			
		||||
    shell_config.read.return_value = 'eval $(thefuck --alias)'
 | 
			
		||||
    main()
 | 
			
		||||
    logs.already_configured.assert_called_once()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_when_successfuly_configured(usage_tracker, shell_pid,
 | 
			
		||||
                                     shell, shell_config, logs):
 | 
			
		||||
def test_when_successfully_configured(usage_tracker_io, shell_pid,
 | 
			
		||||
                                      shell, shell_config, logs):
 | 
			
		||||
    shell.get_history.return_value = ['fuck']
 | 
			
		||||
    shell_pid.return_value = 12
 | 
			
		||||
    _change_tracker(usage_tracker, 12)
 | 
			
		||||
    _change_tracker(usage_tracker_io, 12)
 | 
			
		||||
    shell_config.read.return_value = ''
 | 
			
		||||
    main()
 | 
			
		||||
    shell_config.write.assert_any_call('eval $(thefuck --alias)')
 | 
			
		||||
 
 | 
			
		||||
@@ -115,11 +115,10 @@ class TestCommand(object):
 | 
			
		||||
 | 
			
		||||
    @pytest.fixture(autouse=True)
 | 
			
		||||
    def prepare(self, monkeypatch):
 | 
			
		||||
        monkeypatch.setattr('thefuck.types.os.environ', {})
 | 
			
		||||
        monkeypatch.setattr('thefuck.types.Command._wait_output',
 | 
			
		||||
                            staticmethod(lambda *_: True))
 | 
			
		||||
 | 
			
		||||
    def test_from_script_calls(self, Popen, settings):
 | 
			
		||||
    def test_from_script_calls(self, Popen, settings, os_environ):
 | 
			
		||||
        settings.env = {}
 | 
			
		||||
        assert Command.from_raw_script(
 | 
			
		||||
            ['apt-get', 'search', 'vim']) == Command(
 | 
			
		||||
@@ -129,7 +128,7 @@ class TestCommand(object):
 | 
			
		||||
                                      stdin=PIPE,
 | 
			
		||||
                                      stdout=PIPE,
 | 
			
		||||
                                      stderr=PIPE,
 | 
			
		||||
                                      env={})
 | 
			
		||||
                                      env=os_environ)
 | 
			
		||||
 | 
			
		||||
    @pytest.mark.parametrize('script, result', [
 | 
			
		||||
        ([''], None),
 | 
			
		||||
 
 | 
			
		||||
@@ -206,8 +206,7 @@ class TestGetValidHistoryWithoutCurrent(object):
 | 
			
		||||
                            return_value='fuck')
 | 
			
		||||
 | 
			
		||||
    @pytest.fixture(autouse=True)
 | 
			
		||||
    def bins(self, mocker, monkeypatch):
 | 
			
		||||
        monkeypatch.setattr('thefuck.conf.os.environ', {'PATH': 'path'})
 | 
			
		||||
    def bins(self, mocker):
 | 
			
		||||
        callables = list()
 | 
			
		||||
        for name in ['diff', 'ls', 'café']:
 | 
			
		||||
            bin_mock = mocker.Mock(name=name)
 | 
			
		||||
 
 | 
			
		||||
@@ -63,3 +63,5 @@ SETTINGS_HEADER = u"""# The Fuck settings file
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
ARGUMENT_PLACEHOLDER = 'THEFUCK_ARGUMENT_PLACEHOLDER'
 | 
			
		||||
 | 
			
		||||
CONFIGURATION_TIMEOUT = 60
 | 
			
		||||
 
 | 
			
		||||
@@ -4,9 +4,11 @@ from .system import init_output
 | 
			
		||||
init_output()
 | 
			
		||||
 | 
			
		||||
import os  # noqa: E402
 | 
			
		||||
from psutil import Process  # noqa: E402
 | 
			
		||||
import json  # noqa: E402
 | 
			
		||||
import time  # noqa: E402
 | 
			
		||||
import six  # noqa: E402
 | 
			
		||||
from . import logs  # noqa: E402
 | 
			
		||||
from psutil import Process  # noqa: E402
 | 
			
		||||
from . import logs, const  # noqa: E402
 | 
			
		||||
from .shells import shell  # noqa: E402
 | 
			
		||||
from .conf import settings  # noqa: E402
 | 
			
		||||
from .system import Path  # noqa: E402
 | 
			
		||||
@@ -30,19 +32,41 @@ def _get_not_configured_usage_tracker_path():
 | 
			
		||||
 | 
			
		||||
def _record_first_run():
 | 
			
		||||
    """Records shell pid to tracker file."""
 | 
			
		||||
    with _get_not_configured_usage_tracker_path().open('w') as tracker:
 | 
			
		||||
        tracker.write(six.text_type(_get_shell_pid()))
 | 
			
		||||
    info = {'pid': _get_shell_pid(),
 | 
			
		||||
            'time': time.time()}
 | 
			
		||||
 | 
			
		||||
    mode = 'wb' if six.PY2 else 'w'
 | 
			
		||||
    with _get_not_configured_usage_tracker_path().open(mode) as tracker:
 | 
			
		||||
        json.dump(info, tracker)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _get_previous_command():
 | 
			
		||||
    history = shell.get_history()
 | 
			
		||||
 | 
			
		||||
    if history:
 | 
			
		||||
        return history[-1]
 | 
			
		||||
    else:
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _is_second_run():
 | 
			
		||||
    """Returns `True` when we know that `fuck` called second time."""
 | 
			
		||||
    tracker_path = _get_not_configured_usage_tracker_path()
 | 
			
		||||
    if not tracker_path.exists() or not shell.get_history()[-1] == 'fuck':
 | 
			
		||||
    if not tracker_path.exists():
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    current_pid = _get_shell_pid()
 | 
			
		||||
    with tracker_path.open('r') as tracker:
 | 
			
		||||
        return tracker.read() == six.text_type(current_pid)
 | 
			
		||||
        try:
 | 
			
		||||
            info = json.load(tracker)
 | 
			
		||||
        except ValueError:
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
    if not (isinstance(info, dict) and info.get('pid') == current_pid):
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    return (_get_previous_command() == 'fuck' or
 | 
			
		||||
            time.time() - info.get('time', 0) < const.CONFIGURATION_TIMEOUT)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _is_already_configured(configuration_details):
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
import os
 | 
			
		||||
import pickle
 | 
			
		||||
import pkg_resources
 | 
			
		||||
import re
 | 
			
		||||
import shelve
 | 
			
		||||
import six
 | 
			
		||||
@@ -108,9 +107,7 @@ def get_all_executables():
 | 
			
		||||
            return fallback
 | 
			
		||||
 | 
			
		||||
    tf_alias = get_alias()
 | 
			
		||||
    tf_entry_points = get_installation_info().get_entry_map()\
 | 
			
		||||
                                             .get('console_scripts', {})\
 | 
			
		||||
                                             .keys()
 | 
			
		||||
    tf_entry_points = ['thefuck', 'fuck']
 | 
			
		||||
 | 
			
		||||
    bins = [exe.name.decode('utf8') if six.PY2 else exe.name
 | 
			
		||||
            for path in os.environ.get('PATH', '').split(':')
 | 
			
		||||
@@ -255,6 +252,8 @@ cache.disabled = False
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_installation_info():
 | 
			
		||||
    import pkg_resources
 | 
			
		||||
 | 
			
		||||
    return pkg_resources.require('thefuck')[0]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user