@Override
  public Object @NotNull [] getVariants() {
    final List<LookupElement> ret = new ArrayList<>();

    // Use real context here to enable correct completion and resolve in case of PyExpressionCodeFragment!!!
    final PyQualifiedExpression originalElement = CompletionUtilCoreImpl.getOriginalElement(myElement);
    final PyQualifiedExpression element = originalElement != null ? originalElement : myElement;

    final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(element);
    final LanguageLevel languageLevel = LanguageLevel.forElement(myElement);
    final CompletionVariantsProcessor processor = new CompletionVariantsProcessor(element, e -> {
      if (builtinCache.isBuiltin(e)) {
        if (e instanceof PyImportElement) {
          return false;
        }

        final String name = e instanceof PyElement ? ((PyElement)e).getName() : null;
        if (PyUtil.getInitialUnderscores(name) == 1) {
          return false;
        }

        if (languageLevel.isPython2() && PyNames.PRINT.equals(name)) {
          final PyFile file = PyUtil.as(myElement.getContainingFile(), PyFile.class);
          if (file != null && !file.hasImportFromFuture(FutureFeature.PRINT_FUNCTION)) {
            return false;
          }
        }
      } else if (ScopeUtil.getScopeOwner(e) == ScopeUtil.getScopeOwner(element)) {
        return PyDefUseUtil.isDefinedBefore(e, element);
      }
      return true;
    }, null);

    PyResolveUtil.scopeCrawlUp(processor, element, null, null);

    // This method is probably called for completion, so use appropriate context here
    // in a call, include function's arg names
    final TypeEvalContext context = TypeEvalContext.codeCompletion(element.getProject(), element.getContainingFile());
    KeywordArgumentCompletionUtil.collectFunctionArgNames(element, ret, context, true);
    // include builtin names
    final PyFile builtinsFile = builtinCache.getBuiltinsFile();
    if (builtinsFile != null) {
      PyResolveUtil.scopeCrawlUp(processor, builtinsFile, null, null);
    }

    if (PyUtil.getInitialUnderscores(element.getName()) >= 2) {
      // if we're a normal module, add module's attrs
      if (PyPsiUtils.getRealContext(element).getContainingFile() instanceof PyFile) {
        for (String name : PyModuleType.getPossibleInstanceMembers()) {
          ret.add(LookupElementBuilder.create(name).withIcon(IconManager.getInstance().getPlatformIcon(com.intellij.ui.PlatformIcons.Field)));
        }
      }

      // if we're inside method, add implicit __class__
      if (!languageLevel.isPython2()) {
        Optional
          .ofNullable(PsiTreeUtil.getParentOfType(myElement, PyFunction.class))
          .map(PyFunction::getContainingClass)
          .ifPresent(pyClass -> ret.add(LookupElementBuilder.create(PyNames.__CLASS__)));
      }
    }

    ret.addAll(getOriginalElements(processor));
    return ret.toArray();
  }
@Override
  public Object @NotNull [] getVariants()