-1

In Python 3.7.2 I have two classes that are referencing each other.

I've looked at the question and answers in: Circular (or cyclic) imports in Python

and they don't answer the question of how to keep type-hinting and auto-completion capabilities when having a cyclic import. In order to allow Pycharm to auto-complete code, I am asking this question.

Class #1 represents ElasticSearch Server and imports class #2 as its member, in order to expose it as internal search capabilities.

Class #2 represents a bunch of search JSONs patterns and imports class #1 in order to define the type of an instance it receives of class #1. This allows Class #2 to run the GET\POST methods that are defined in Class #1.

This looks something like this:

class SimplifiedElasticSearch

from framework.elk.search_patterns import SearchPatterns

class SimplifiedElasticSearch(object):
    ...
    ...

class SearchPatterns

from framework.elk.simplified_elastic_search import SimplifiedElasticSearch

class SearchPatterns(object):

    def __init__(self, es_server: SimplifiedElasticSearch):
        ...
        ...

You can see that both module import each other and an instance of class SimplifiedElasticSearch is passed to class SearchPatterns upon __ init __


This results in an import error

ImportError: cannot import name 'SimplifiedElasticSearch' from 'framework.elk.simplified_elastic_search'

To prevent the error, one option is to NOT import class SimplifiedElasticSearch, i.d. remove the line

from framework.elk.simplified_elastic_search import SimplifiedElasticSearch

and write the code with auto-completion and type-hinting for the instance of SimplifiedElasticSearch that I pass to the class SearchPatterns


How can I keep the auto-completion and type hinting for such a case?

RaamEE
  • 3,017
  • 4
  • 33
  • 53
  • Possible duplicate of [Circular (or cyclic) imports in Python](https://stackoverflow.com/questions/744373/circular-or-cyclic-imports-in-python) – Netwave Apr 25 '19 at 06:38
  • 1
    it's better to refactor and make your code more independent and remove core package in different location and then use them from there in your code, – sahasrara62 Apr 25 '19 at 06:43
  • @Netwave, this is not a duplicate. The answer you suggest indeed solves the cyclic import issue, but doesn't answer the problem I raise of "How to keep the type hinting of the referenced instance of class #1 in class #2". – RaamEE Apr 25 '19 at 06:48
  • @prashantrana, I've considered changing the structure of the classes, but decided against it. Python allows for such cyclic imports and references, but fails in this specific case. This is why I ask and answer this issue. – RaamEE Apr 25 '19 at 06:50
  • 1
    @RaamEE python allow this , but refactory and structuring would be more efficient in long run – sahasrara62 Apr 25 '19 at 07:51

1 Answers1

-1

I suggest the following pattern. Using it will allow auto-completion and type hinting to work properly.

simplified_elastic_search.py

import search_patterns 

class SimplifiedElasticSearch(object):
    def __init__(self):
        pass

    def print_ses(self):
        print('SimplifiedElasticSearch')

if __name__ == '__main__':
    ses = SimplifiedElasticSearch()
    ses.print_ses()

    sp = search_patterns.SearchPatterns(ses)
    sp.print_sp()

search_patterns.py

import simplified_elastic_search 

class SearchPatterns(object):
    def __init__(self, ses):
        self.ses: simplified_elastic_search.SimplifiedElasticSearch = ses

    def print_sp(self):
        print('SearchPatterns-1-----------------')
        self.sp.print_sp()
        print('SearchPatterns-2-----------------')

You cannot import classes SimplifiedElasticSearch & SearchPatterns using this syntax

from simplified_elastic_search import SimplifiedElasticSearch  
from search_patterns import SearchPatterns

You cannot declare the type of parameter ses in class SearchPatterns's __ init __ method, but you can "cast" it this way:

def __init__(self, ses):
    self.ses: simplified_elastic_search.SimplifiedElasticSearch = ses
RaamEE
  • 3,017
  • 4
  • 33
  • 53