# -*- coding: utf-8 -*-
# Copyright (c) 2015, Almar Klein
# Distributed under the (new) BSD License. See LICENSE.txt for more info.

""" Functionality used for testing. This code itself is not covered in tests.
"""

from __future__ import absolute_import, print_function, division

import os
import sys
import inspect

import pytest

# Get root dir
PACKAGE_NAME = __name__.split('.')[0]

# Get root dir
THIS_DIR = os.path.abspath(os.path.dirname(__file__))
ROOT_DIR = THIS_DIR
for i in range(9):
    ROOT_DIR = os.path.dirname(ROOT_DIR)
    if os.path.isfile(os.path.join(ROOT_DIR, '.gitignore')):
        break


STYLE_IGNORES = ['E226', 
                 'E241', 
                 'E265', 
                 'E266',  # too many leading '#' for block comment
                 'E402',  # module level import not at top of file
                 'E731',  # do not assign a lambda expression, use a def
                 'W291', 
                 'W293',
                 ]


## Functions to use in tests

def run_tests_if_main(show_coverage=False):
    """ Run tests in a given file if it is run as a script
    
    Coverage is reported for running this single test. Set show_coverage to
    launch the report in the web browser.
    """
    local_vars = inspect.currentframe().f_back.f_locals
    if not local_vars.get('__name__', '') == '__main__':
        return
    # we are in a "__main__"
    os.chdir(ROOT_DIR)
    fname = str(local_vars['__file__'])
    _clear_our_modules()
    _enable_faulthandler()
    pytest.main('-v -x --color=yes --cov flexx '
                '--cov-config .coveragerc --cov-report html %s' % repr(fname))
    if show_coverage:
        import webbrowser
        fname = os.path.join(ROOT_DIR, 'htmlcov', 'index.html')
        webbrowser.open_new_tab(fname)


## Requirements

def _enable_faulthandler():
    """ Enable faulthandler (if we can), so that we get tracebacks
    on segfaults.
    """
    try:
        import faulthandler
        faulthandler.enable()
        print('Faulthandler enabled')
    except Exception:
        print('Could not enable faulthandler')


def _clear_our_modules():
    # Remove ourselves from sys.modules to force an import
    for key in list(sys.modules.keys()):
        if key.startswith(PACKAGE_NAME) and 'testing' not in key:
            del sys.modules[key]


class FileForTesting(object):
    """ Alternative to stdout that makes path relative to ROOT_DIR
    """
    def __init__(self, original):
        self._original = original
    
    def write(self, msg):
        if msg.startswith(ROOT_DIR):
            msg = os.path.relpath(msg, ROOT_DIR)
        self._original.write(msg)
        self._original.flush()
    
    def flush(self):
        self._original.flush()
    
    def revert(self):
        sys.stdout = self._original

@@ -97,45 +97,14 @@
 nse.
- See LICENSE.txt for more info.
 %0A%0A%22%22%22
- 
+%0A
 Func
@@ -133,57 +133,345 @@
 ting
+, based on pytest
 . This 
-c
+m
 od
+ul
 e i
-tself is not covered in tests.
+s designed%0Ato just work, without modification, in most projects.%0A%0AWrite your tests like this:%0A%0A    from yourproject.xxx.testing import run_tests_if_main, raises, skipif%0A    ...%0A    run_tests_if_main()%0A%0AThen you can run the test file as a script, which will run all tests%0Aand report coverage. Magic!
 %0A%22%22%22%0A%0A
+%0A
 from
@@ -584,30 +584,16 @@
 pytest%0A%0A
-# Get root dir
 %0APACKAGE
@@ -630,16 +630,24 @@
 %0A%0A# Get 
+project 
 root dir
@@ -800,455 +800,361 @@
 ath.
-isfile(os.path.join(ROOT_DIR, '.gitignore')):%0A        break%0A%0A%0ASTYLE_IGNORES = %5B'E226', %0A                 'E241', %0A                 'E265', %0A                 'E266',  # too many leading '#' for block comment%0A                 'E402',  # module level import not at top of file%0A                 'E731',  # do not assign a lambda expression, use a def%0A                 'W291', %0A                 'W293',%0A                 %5D%0A%0A%0A## Functions to use in tests
+basename(ROOT_DIR) == PACKAGE_NAME:%0A        ROOT_DIR = os.path.dirname(ROOT_DIR)%0A        break%0Aelse:%0A    print('testing.py could not find project root dir, '%0A          'using testing.py directory instead.')%0A    ROOT_DIR = THIS_DIR%0A%0A%0A# Inject some function names so they can be obtained with one import%0Araises = pytest.raises%0Askipif = pytest.mark.skipif%0A
 %0A%0Ade
@@ -1702,13 +1702,10 @@
 cov 
-flexx
+%25s
  '%0A 
@@ -1768,16 +1768,47 @@
 ml %25s' %25
+%0A                (PACKAGE_NAME,
  repr(fn
@@ -1812,16 +1812,17 @@
 (fname))
+)
 %0A    if 
@@ -1971,25 +1971,8 @@
 )%0A%0A%0A
-## Requirements%0A%0A
 def 
@@ -2294,17 +2294,19 @@
 ():%0A    
-#
+%22%22%22
  Remove 
@@ -2350,16 +2350,25 @@
 n import
+.%0A    %22%22%22
 %0A    for
@@ -2504,481 +2504,4 @@
 ey%5D%0A
-%0A%0Aclass FileForTesting(object):%0A    %22%22%22 Alternative to stdout that makes path relative to ROOT_DIR%0A    %22%22%22%0A    def __init__(self, original):%0A        self._original = original%0A    %0A    def write(self, msg):%0A        if msg.startswith(ROOT_DIR):%0A            msg = os.path.relpath(msg, ROOT_DIR)%0A        self._original.write(msg)%0A        self._original.flush()%0A    %0A    def flush(self):%0A        self._original.flush()%0A    %0A    def revert(self):%0A        sys.stdout = self._original%0A

update testing.py