def get_breakpoint(plugin, py_db, pydb_frame, frame, event, args): py_db = args[0] _filename = args[1] info = args[2] break_type = 'jinja2' if event == 'line' and info.pydev_state != STATE_SUSPEND and py_db.jinja2_breakpoints and _is_jinja2_render_call(frame): jinja_template = frame.f_globals.get('__jinja_template__') if jinja_template is None: return False, None, None, break_type original_filename = _get_jinja2_template_original_filename(frame) if original_filename is not None: pydev_log.debug("Jinja2 is rendering a template: %s", original_filename) canonical_normalized_filename = canonical_normalized_path(original_filename) jinja2_breakpoints_for_file = py_db.jinja2_breakpoints.get(canonical_normalized_filename) if jinja2_breakpoints_for_file: jinja2_validation_info = py_db.jinja2_validation_info jinja2_validation_info.verify_breakpoints(py_db, canonical_normalized_filename, jinja2_breakpoints_for_file, jinja_template) template_lineno = _get_jinja2_template_line(frame) if template_lineno is not None: jinja2_breakpoint = jinja2_breakpoints_for_file.get(template_lineno) if jinja2_breakpoint is not None: new_frame = Jinja2TemplateFrame(frame, original_filename, template_lineno) return True, jinja2_breakpoint, new_frame, break_type return False, None, None, break_type
def cmd_ignore_thrown_exception_at(self, py_db, cmd_id, seq, text): if text: replace = 'REPLACE:' # Not all 3.x versions support u'REPLACE:', so, doing workaround. if not IS_PY3K: replace = unicode(replace) # noqa if text.startswith(replace): text = text[8:] py_db.filename_to_lines_where_exceptions_are_ignored.clear() if text: for line in text.split('||'): # Can be bulk-created (one in each line) original_filename, line_number = line.split('|') original_filename = self.api.filename_to_server(original_filename) canonical_normalized_filename = pydevd_file_utils.canonical_normalized_path(original_filename) absolute_filename = pydevd_file_utils.absolute_path(original_filename) if os.path.exists(absolute_filename): lines_ignored = py_db.filename_to_lines_where_exceptions_are_ignored.get(canonical_normalized_filename) if lines_ignored is None: lines_ignored = py_db.filename_to_lines_where_exceptions_are_ignored[canonical_normalized_filename] = {} lines_ignored[int(line_number)] = 1 else: sys.stderr.write('pydev debugger: warning: trying to ignore exception thrown'\ ' on file that does not exist: %s (will have no effect)\n' % (absolute_filename,))
def can_skip(plugin, pydb, frame): if pydb.jinja2_breakpoints and _is_jinja2_render_call(frame): filename = _get_jinja2_template_original_filename(frame) if filename is not None: canonical_normalized_filename = canonical_normalized_path(filename) jinja2_breakpoints_for_file = pydb.jinja2_breakpoints.get(canonical_normalized_filename) if jinja2_breakpoints_for_file: return False if pydb.jinja2_exception_break: name = frame.f_code.co_name if IS_PY2: if name == 'fail': module_name = frame.f_globals.get('__name__', '') if module_name == 'jinja2.parser': return False else: # errors in compile time if name in ('template', 'top-level template code', '<module>') or name.startswith('block '): f_back = frame.f_back module_name = '' if f_back is not None: module_name = f_back.f_globals.get('__name__', '') if module_name.startswith('jinja2.'): return False return True
def get_breakpoint(plugin, pydb, pydb_frame, frame, event, args): pydb = args[0] _filename = args[1] info = args[2] new_frame = None jinja2_breakpoint = None flag = False break_type = 'jinja2' if event == 'line' and info.pydev_state != STATE_SUSPEND and \ pydb.jinja2_breakpoints and _is_jinja2_render_call(frame): original_filename = _get_jinja2_template_original_filename(frame) if original_filename is not None: pydev_log.debug("Jinja2 is rendering a template: %s", original_filename) canonical_normalized_filename = canonical_normalized_path(original_filename) jinja2_breakpoints_for_file = pydb.jinja2_breakpoints.get(canonical_normalized_filename) if jinja2_breakpoints_for_file: template_lineno = _get_jinja2_template_line(frame) if template_lineno is not None: jinja2_breakpoint = jinja2_breakpoints_for_file.get(template_lineno) if jinja2_breakpoint is not None: flag = True new_frame = Jinja2TemplateFrame(frame, original_filename, template_lineno) return flag, jinja2_breakpoint, new_frame, break_type
def get_breakpoint(plugin, main_debugger, pydb_frame, frame, event, args): main_debugger = args[0] _filename = args[1] info = args[2] flag = False django_breakpoint = None new_frame = None breakpoint_type = 'django' if event == 'call' and info.pydev_state != STATE_SUSPEND and main_debugger.django_breakpoints and _is_django_render_call( frame): original_filename = _get_template_original_file_name_from_frame(frame) pydev_log.debug("Django is rendering a template: %s", original_filename) canonical_normalized_filename = canonical_normalized_path( original_filename) django_breakpoints_for_file = main_debugger.django_breakpoints.get( canonical_normalized_filename) if django_breakpoints_for_file: pydev_log.debug("Breakpoints for that file: %s", django_breakpoints_for_file) template_line = _get_template_line(frame) pydev_log.debug("Tracing template line: %s", template_line) if template_line in django_breakpoints_for_file: django_breakpoint = django_breakpoints_for_file[template_line] flag = True new_frame = DjangoTemplateFrame(frame) return flag, django_breakpoint, new_frame, breakpoint_type
def remove_breakpoint(self, py_db, received_filename, breakpoint_type, breakpoint_id): ''' :param str received_filename: Note: must be sent as it was received in the protocol. It may be translated in this function. :param str breakpoint_type: One of: 'python-line', 'django-line', 'jinja2-line'. :param int breakpoint_id: ''' for key, val in dict_items(py_db.api_received_breakpoints): original_filename, existing_breakpoint_id = key _new_filename, _api_add_breakpoint_params = val if received_filename == original_filename and existing_breakpoint_id == breakpoint_id: del py_db.api_received_breakpoints[key] break else: pydev_log.info( 'Did not find breakpoint to remove: %s (breakpoint id: %s)', received_filename, breakpoint_id) file_to_id_to_breakpoint = None received_filename = self.filename_to_server(received_filename) canonical_normalized_filename = pydevd_file_utils.canonical_normalized_path(received_filename) if breakpoint_type == 'python-line': breakpoints = py_db.breakpoints file_to_id_to_breakpoint = py_db.file_to_id_to_line_breakpoint elif py_db.plugin is not None: result = py_db.plugin.get_breakpoints(py_db, breakpoint_type) if result is not None: file_to_id_to_breakpoint = py_db.file_to_id_to_plugin_breakpoint breakpoints = result if file_to_id_to_breakpoint is None: pydev_log.critical('Error removing breakpoint. Cannot handle breakpoint of type %s', breakpoint_type) else: try: id_to_pybreakpoint = file_to_id_to_breakpoint.get(canonical_normalized_filename, {}) if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0: existing = id_to_pybreakpoint[breakpoint_id] pydev_log.info('Removed breakpoint:%s - line:%s - func_name:%s (id: %s)\n' % ( canonical_normalized_filename, existing.line, existing.func_name.encode('utf-8'), breakpoint_id)) del id_to_pybreakpoint[breakpoint_id] py_db.consolidate_breakpoints(canonical_normalized_filename, id_to_pybreakpoint, breakpoints) if py_db.plugin is not None: py_db.has_plugin_line_breaks = py_db.plugin.has_line_breaks() except KeyError: pydev_log.info("Error removing breakpoint: Breakpoint id not found: %s id: %s. Available ids: %s\n", canonical_normalized_filename, breakpoint_id, dict_keys(id_to_pybreakpoint)) py_db.on_breakpoints_changed(removed=True)
def _load_filters(): global py_test_accept_filter if py_test_accept_filter is None: py_test_accept_filter = os.environ.get('PYDEV_PYTEST_SKIP') if py_test_accept_filter: py_test_accept_filter = pickle.loads( zlib.decompress(base64.b64decode(py_test_accept_filter))) # Newer versions of pytest resolve symlinks, so, we # may need to filter with a resolved path too. new_dct = {} for filename, value in py_test_accept_filter.items(): new_dct[canonical_normalized_path(str( Path(filename).resolve()))] = value py_test_accept_filter.update(new_dct) else: py_test_accept_filter = {}
def get_breakpoint(plugin, py_db, pydb_frame, frame, event, args): py_db = args[0] _filename = args[1] info = args[2] breakpoint_type = 'django' if event == 'call' and info.pydev_state != STATE_SUSPEND and py_db.django_breakpoints and _is_django_render_call( frame): original_filename = _get_template_original_file_name_from_frame(frame) pydev_log.debug("Django is rendering a template: %s", original_filename) canonical_normalized_filename = canonical_normalized_path( original_filename) django_breakpoints_for_file = py_db.django_breakpoints.get( canonical_normalized_filename) if django_breakpoints_for_file: # At this point, let's validate whether template lines are correct. if IS_DJANGO19_OR_HIGHER: django_validation_info = py_db.django_validation_info context = frame.f_locals['context'] django_template = context.template django_validation_info.verify_breakpoints( py_db, canonical_normalized_filename, django_breakpoints_for_file, django_template) pydev_log.debug("Breakpoints for that file: %s", django_breakpoints_for_file) template_line = _get_template_line(frame) pydev_log.debug("Tracing template line: %s", template_line) if template_line in django_breakpoints_for_file: django_breakpoint = django_breakpoints_for_file[template_line] new_frame = DjangoTemplateFrame(frame) return True, django_breakpoint, new_frame, breakpoint_type return False, None, None, breakpoint_type
def pytest_collection_modifyitems(session, config, items): # A note: in xdist, this is not called on the main process, only in the # secondary nodes, so, we'll actually make the filter and report it multiple # times. connect_to_server_for_communication_to_xml_rpc_on_xdist() _load_filters() if not py_test_accept_filter: pydev_runfiles_xml_rpc.notifyTestsCollected(len(items)) return # Keep on going (nothing to filter) new_items = [] for item in items: f = canonical_normalized_path(str(item.parent.fspath)) name = item.name if f not in py_test_accept_filter: # print('Skip file: %s' % (f,)) continue # Skip the file i = name.find('[') name_without_parametrize = None if i > 0: name_without_parametrize = name[:i] accept_tests = py_test_accept_filter[f] if item.cls is not None: class_name = item.cls.__name__ else: class_name = None for test in accept_tests: if test == name: # Direct match of the test (just go on with the default # loading) new_items.append(item) break if name_without_parametrize is not None and test == name_without_parametrize: # This happens when parameterizing pytest tests on older versions # of pytest where the test name doesn't include the fixture name # in it. new_items.append(item) break if class_name is not None: if test == class_name + '.' + name: new_items.append(item) break if name_without_parametrize is not None and test == class_name + '.' + name_without_parametrize: new_items.append(item) break if class_name == test: new_items.append(item) break else: pass # print('Skip test: %s.%s. Accept: %s' % (class_name, name, accept_tests)) # Modify the original list items[:] = new_items pydev_runfiles_xml_rpc.notifyTestsCollected(len(items))
def add_breakpoint(self, py_db, original_filename, breakpoint_type, breakpoint_id, line, condition, func_name, expression, suspend_policy, hit_condition, is_logpoint, adjust_line=False): ''' :param str original_filename: Note: must be sent as it was received in the protocol. It may be translated in this function and its final value will be available in the returned _AddBreakpointResult. :param str breakpoint_type: One of: 'python-line', 'django-line', 'jinja2-line'. :param int breakpoint_id: :param int line: Note: it's possible that a new line was actually used. If that's the case its final value will be available in the returned _AddBreakpointResult. :param condition: Either None or the condition to activate the breakpoint. :param str func_name: If "None" (str), may hit in any context. Empty string will hit only top level. Any other value must match the scope of the method to be matched. :param str expression: None or the expression to be evaluated. :param suspend_policy: Either "NONE" (to suspend only the current thread when the breakpoint is hit) or "ALL" (to suspend all threads when a breakpoint is hit). :param str hit_condition: An expression where `@HIT@` will be replaced by the number of hits. i.e.: `@HIT@ == x` or `@HIT@ >= x` :param bool is_logpoint: If True and an expression is passed, pydevd will create an io message command with the result of the evaluation. :return _AddBreakpointResult: ''' assert original_filename.__class__ == str, 'Expected str, found: %s' % ( original_filename.__class__, ) # i.e.: bytes on py2 and str on py3 pydev_log.debug('Request for breakpoint in: %s line: %s', original_filename, line) # Parameters to reapply breakpoint. api_add_breakpoint_params = (original_filename, breakpoint_type, breakpoint_id, line, condition, func_name, expression, suspend_policy, hit_condition, is_logpoint) translated_filename = self.filename_to_server( original_filename) # Apply user path mapping. pydev_log.debug('Breakpoint (after path translation) in: %s line: %s', translated_filename, line) func_name = self.to_str(func_name) assert translated_filename.__class__ == str # i.e.: bytes on py2 and str on py3 assert func_name.__class__ == str # i.e.: bytes on py2 and str on py3 # Apply source mapping (i.e.: ipython). source_mapped_filename, new_line, multi_mapping_applied = py_db.source_mapping.map_to_server( translated_filename, line) if multi_mapping_applied: pydev_log.debug( 'Breakpoint (after source mapping) in: %s line: %s', source_mapped_filename, new_line) # Note that source mapping is internal and does not change the resulting filename nor line # (we want the outside world to see the line in the original file and not in the ipython # cell, otherwise the editor wouldn't be correct as the returned line is the line to # which the breakpoint will be moved in the editor). result = self._AddBreakpointResult(original_filename, line) # If a multi-mapping was applied, consider it the canonical / source mapped version (translated to ipython cell). translated_absolute_filename = source_mapped_filename canonical_normalized_filename = pydevd_file_utils.normcase( source_mapped_filename) line = new_line else: translated_absolute_filename = pydevd_file_utils.absolute_path( translated_filename) canonical_normalized_filename = pydevd_file_utils.canonical_normalized_path( translated_filename) if adjust_line and not translated_absolute_filename.startswith( '<'): # Validate breakpoints and adjust their positions. try: lines = sorted( _get_code_lines(translated_absolute_filename)) except Exception: pass else: if line not in lines: # Adjust to the first preceding valid line. idx = bisect.bisect_left(lines, line) if idx > 0: line = lines[idx - 1] result = self._AddBreakpointResult(original_filename, line) py_db.api_received_breakpoints[(original_filename, breakpoint_id)] = ( canonical_normalized_filename, api_add_breakpoint_params) if not translated_absolute_filename.startswith('<'): # Note: if a mapping pointed to a file starting with '<', don't validate. if not pydevd_file_utils.exists(translated_absolute_filename): result.error_code = self.ADD_BREAKPOINT_FILE_NOT_FOUND return result if (py_db.is_files_filter_enabled and not py_db.get_require_module_for_filters() and py_db.apply_files_filter( self._DummyFrame(translated_absolute_filename), translated_absolute_filename, False)): # Note that if `get_require_module_for_filters()` returns False, we don't do this check. # This is because we don't have the module name given a file at this point (in # runtime it's gotten from the frame.f_globals). # An option could be calculate it based on the filename and current sys.path, # but on some occasions that may be wrong (for instance with `__main__` or if # the user dynamically changes the PYTHONPATH). # Note: depending on the use-case, filters may be changed, so, keep on going and add the # breakpoint even with the error code. result.error_code = self.ADD_BREAKPOINT_FILE_EXCLUDED_BY_FILTERS if breakpoint_type == 'python-line': added_breakpoint = LineBreakpoint(line, condition, func_name, expression, suspend_policy, hit_condition=hit_condition, is_logpoint=is_logpoint) breakpoints = py_db.breakpoints file_to_id_to_breakpoint = py_db.file_to_id_to_line_breakpoint supported_type = True else: add_plugin_breakpoint_result = None plugin = py_db.get_plugin_lazy_init() if plugin is not None: add_plugin_breakpoint_result = plugin.add_breakpoint( 'add_line_breakpoint', py_db, breakpoint_type, canonical_normalized_filename, line, condition, expression, func_name, hit_condition=hit_condition, is_logpoint=is_logpoint) if add_plugin_breakpoint_result is not None: supported_type = True added_breakpoint, breakpoints = add_plugin_breakpoint_result file_to_id_to_breakpoint = py_db.file_to_id_to_plugin_breakpoint else: supported_type = False if not supported_type: raise NameError(breakpoint_type) if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0: pydev_log.debug('Added breakpoint:%s - line:%s - func_name:%s\n', canonical_normalized_filename, line, func_name) if canonical_normalized_filename in file_to_id_to_breakpoint: id_to_pybreakpoint = file_to_id_to_breakpoint[ canonical_normalized_filename] else: id_to_pybreakpoint = file_to_id_to_breakpoint[ canonical_normalized_filename] = {} id_to_pybreakpoint[breakpoint_id] = added_breakpoint py_db.consolidate_breakpoints(canonical_normalized_filename, id_to_pybreakpoint, breakpoints) if py_db.plugin is not None: py_db.has_plugin_line_breaks = py_db.plugin.has_line_breaks() py_db.on_breakpoints_changed() return result
def main(): import sys # Separate the nose params and the pydev params. pydev_params = [] other_test_framework_params = [] found_other_test_framework_param = None NOSE_PARAMS = '--nose-params' PY_TEST_PARAMS = '--py-test-params' for arg in sys.argv[1:]: if not found_other_test_framework_param and arg != NOSE_PARAMS and arg != PY_TEST_PARAMS: pydev_params.append(arg) else: if not found_other_test_framework_param: found_other_test_framework_param = arg else: other_test_framework_params.append(arg) try: # Convert to the case stored in the filesystem import win32api def get_with_filesystem_case(f): return win32api.GetLongPathName(win32api.GetShortPathName(f)) except: def get_with_filesystem_case(f): return f # Here we'll run either with nose or with the pydev_runfiles. from _pydev_runfiles import pydev_runfiles from _pydev_runfiles import pydev_runfiles_xml_rpc from _pydevd_bundle import pydevd_constants from pydevd_file_utils import canonical_normalized_path DEBUG = 0 if DEBUG: sys.stdout.write('Received parameters: %s\n' % (sys.argv,)) sys.stdout.write('Params for pydev: %s\n' % (pydev_params,)) if found_other_test_framework_param: sys.stdout.write('Params for test framework: %s, %s\n' % (found_other_test_framework_param, other_test_framework_params)) try: configuration = pydev_runfiles.parse_cmdline([sys.argv[0]] + pydev_params) except: sys.stderr.write('Command line received: %s\n' % (sys.argv,)) raise pydev_runfiles_xml_rpc.initialize_server(configuration.port) # Note that if the port is None, a Null server will be initialized. NOSE_FRAMEWORK = "nose" PY_TEST_FRAMEWORK = "py.test" test_framework = None # Default (pydev) try: if found_other_test_framework_param: if found_other_test_framework_param == NOSE_PARAMS: test_framework = NOSE_FRAMEWORK import nose elif found_other_test_framework_param == PY_TEST_PARAMS: test_framework = PY_TEST_FRAMEWORK import pytest else: raise ImportError('Test framework: %s not supported.' % (found_other_test_framework_param,)) else: raise ImportError() except ImportError: if found_other_test_framework_param: raise test_framework = None # Clear any exception that may be there so that clients don't see it. # See: https://sourceforge.net/tracker/?func=detail&aid=3408057&group_id=85796&atid=577329 if hasattr(sys, 'exc_clear'): sys.exc_clear() if not test_framework: return pydev_runfiles.main(configuration) # Note: still doesn't return a proper value. else: # We'll convert the parameters to what nose or py.test expects. # The supported parameters are: # runfiles.py --config-file|-t|--tests <Test.test1,Test2> dirs|files --nose-params xxx yyy zzz # (all after --nose-params should be passed directly to nose) # In java: # --tests = Constants.ATTR_UNITTEST_TESTS # --config-file = Constants.ATTR_UNITTEST_CONFIGURATION_FILE # The only thing actually handled here are the tests that we want to run, which we'll # handle and pass as what the test framework expects. py_test_accept_filter = {} files_to_tests = configuration.files_to_tests if files_to_tests: # Handling through the file contents (file where each line is a test) files_or_dirs = [] for file, tests in files_to_tests.items(): if test_framework == NOSE_FRAMEWORK: for test in tests: files_or_dirs.append(file + ':' + test) elif test_framework == PY_TEST_FRAMEWORK: py_test_accept_filter[file] = tests py_test_accept_filter[canonical_normalized_path(file)] = tests files_or_dirs.append(file) else: raise AssertionError('Cannot handle test framework: %s at this point.' % (test_framework,)) else: if configuration.tests: # Tests passed (works together with the files_or_dirs) files_or_dirs = [] for file in configuration.files_or_dirs: if test_framework == NOSE_FRAMEWORK: for t in configuration.tests: files_or_dirs.append(file + ':' + t) elif test_framework == PY_TEST_FRAMEWORK: py_test_accept_filter[file] = configuration.tests py_test_accept_filter[canonical_normalized_path(file)] = configuration.tests files_or_dirs.append(file) else: raise AssertionError('Cannot handle test framework: %s at this point.' % (test_framework,)) else: # Only files or dirs passed (let it do the test-loading based on those paths) files_or_dirs = configuration.files_or_dirs argv = other_test_framework_params + files_or_dirs if test_framework == NOSE_FRAMEWORK: # Nose usage: http://somethingaboutorange.com/mrl/projects/nose/0.11.2/usage.html # show_stdout_option = ['-s'] # processes_option = ['--processes=2'] argv.insert(0, sys.argv[0]) if DEBUG: sys.stdout.write('Final test framework args: %s\n' % (argv[1:],)) from _pydev_runfiles import pydev_runfiles_nose PYDEV_NOSE_PLUGIN_SINGLETON = pydev_runfiles_nose.start_pydev_nose_plugin_singleton(configuration) argv.append('--with-pydevplugin') # Return 'not' because it will return 'success' (so, exit == 0 if success) return not nose.run(argv=argv, addplugins=[PYDEV_NOSE_PLUGIN_SINGLETON]) elif test_framework == PY_TEST_FRAMEWORK: if '--coverage_output_dir' in pydev_params and '--coverage_include' in pydev_params: coverage_output_dir = pydev_params[pydev_params.index('--coverage_output_dir') + 1] coverage_include = pydev_params[pydev_params.index('--coverage_include') + 1] try: import pytest_cov except ImportError: sys.stderr.write('To do a coverage run with pytest the pytest-cov library is needed (i.e.: pip install pytest-cov).\n\n') raise argv.insert(0, '--cov-append') argv.insert(1, '--cov-report=') argv.insert(2, '--cov=%s' % (coverage_include,)) import time os.environ['COVERAGE_FILE'] = os.path.join(coverage_output_dir, '.coverage.%s' % (time.time(),)) if DEBUG: sys.stdout.write('Final test framework args: %s\n' % (argv,)) sys.stdout.write('py_test_accept_filter: %s\n' % (py_test_accept_filter,)) def dotted(p): # Helper to convert path to have dots instead of slashes return os.path.normpath(p).replace(os.sep, "/").replace('/', '.') curr_dir = os.path.realpath('.') curr_dotted = dotted(curr_dir) + '.' # Overcome limitation on py.test: # When searching conftest if we have a structure as: # /my_package # /my_package/conftest.py # /my_package/tests # /my_package/tests/test_my_package.py # The test_my_package won't have access to the conftest contents from the # test_my_package.py file unless the working dir is set to /my_package. # # See related issue (for which we work-around below): # https://bitbucket.org/hpk42/pytest/issue/639/conftest-being-loaded-twice-giving for path in sys.path: path_dotted = dotted(path) if curr_dotted.startswith(path_dotted): os.chdir(path) break remove = [] for i in xrange(len(argv)): arg = argv[i] # Workaround bug in py.test: if we pass the full path it ends up importing conftest # more than once (so, always work with relative paths). if os.path.isfile(arg) or os.path.isdir(arg): # Args must be passed with the proper case in the filesystem (otherwise # python itself may not recognize it). arg = get_with_filesystem_case(arg) argv[i] = arg from os.path import relpath try: # May fail if on different drives arg = relpath(arg) except ValueError: pass else: argv[i] = arg elif '<unable to get>' in arg: remove.append(i) for i in reversed(remove): del argv[i] # To find our runfile helpers (i.e.: plugin)... d = os.path.dirname(__file__) if d not in sys.path: sys.path.insert(0, d) import pickle, zlib, base64 # Update environment PYTHONPATH so that it finds our plugin if using xdist. os.environ['PYTHONPATH'] = os.pathsep.join(sys.path) # Set what should be skipped in the plugin through an environment variable s = base64.b64encode(zlib.compress(pickle.dumps(py_test_accept_filter))) if pydevd_constants.IS_PY3K: s = s.decode('ascii') # Must be str in py3. os.environ['PYDEV_PYTEST_SKIP'] = s # Identifies the main pid (i.e.: if it's not the main pid it has to connect back to the # main pid to give xml-rpc notifications). os.environ['PYDEV_MAIN_PID'] = str(os.getpid()) os.environ['PYDEV_PYTEST_SERVER'] = str(configuration.port) argv.append('-p') argv.append('_pydev_runfiles.pydev_runfiles_pytest2') return pytest.main(argv) else: raise AssertionError('Cannot handle test framework: %s at this point.' % (test_framework,))