I've got a thing that you can do engine.setState(<state class>)
and it will instantiate the class type you give it and start running on the new state.
In SelectFileState
there is a button to go to NewFileState
, and on NewFileState
, there is a button to go back to SelectFileState
.
Now, at the beginning of SelectFileState
, I'm importing NewFileState
(So I can later in the class do engine.setState(NewFileState)
. At the beginning of NewFileState
, I'm also importing SelectFileState
(So I can later go back to SelectFileState
).
However, this creates a circular import, as described in some other posts. Some say that circular imports are indicators bad design, and should be refactored..
I know that I can just fix this problem by importing SelectFileState
right before I need to use it, but I'd rather do things the right way and refactor it.
Now I'm wondering though.. How would you refactor that out?
Thanks.
Edit: Pydsigner suggests that I merge the two files into one, as they are both very related to each other. However, I cannot put EVERY state that has a circular dependency into one file, so there's got to be a better method for that. Any ideas?
2Edit:
I'm circumventing this problem for now by not using the from x import y
syntax, and instead just doing import x
. This is not a preferable solution, and I'd like to know the "Pythonic" way to fix this kind of thing. Just merging files together can't be the fix forever.
The code:
SelectFileState
from states.state import State
from states.newfilestate import NewFileState
from elements.poster import Poster
from elements.label import Label
from elements.button import Button
from elements.trifader import TriFader
import glob
import os
class SelectFileState(State):
def __init__(self, engine):
super().__init__(engine)
def create(self):
self.engine.createElement((0, 0), Poster(self.engine.getImage('gui_loadsave')), 1)
self.engine.createElement((168, 30), Label("Load a game", 40), 2)
self.engine.createElement((400, 470), Button("New save", code=self.engine.createElement, args=((0, 0), TriFader(NewFileState, False), -240)), 3)
ycounter = 150
globs = glob.glob("save\\*.mcw")
for file in globs:
self.engine.createElement((200, ycounter), Button(os.path.basename(file)[:-4]), 2)
ycounter += 50
NewFileState
from states.state import State
from states.selectfilestate import SelectFileState
from elements.poster import Poster
from elements.label import Label
from elements.button import Button
from elements.inputbox import InputBox
from elements.trifader import TriFader
class NewFileState(State):
def __init__(self, engine):
super().__init__(engine)
def create(self):
self.engine.createElement((0, 0), Poster(self.engine.getImage('gui_loadsave')), 1)
self.engine.createElement((135, 30), Label("Make a new save", 40), 2)
self.lvlname = self.engine.createElement((180, 212), InputBox(length=25, text="World name"), 2)
self.engine.createElement((200, 240), Button(text="Ok", code=self.createSave, args=()), 2)
def createSave(self):
open("save\\" + self.lvlname.getText() + ".mcw", 'w')
self.engine.createElement((0, 0), TriFader(SelectFileState), -240)
The easiest way to fix this is to move the path import to the end of the node module. Save this answer.
In simplest terms, a circular import occurs when module A tries to import and use an object from module B, while module B tries to import and use an object from module A. We'll run the code from run.py, which just imports a.py. As you can see, we get an exception as soon as b.py tries to import a.py.
Without seeing code, what would make the most sense is to merge the two files. If they are that closely intertwined, you could probably put them together without anything really oddly out of place.
In Python imports don't have to appear at the beginning of module. In fact they can appear in functions, so in NewFileState.py you could move the import of SelectFileState into NewFileState.create and you could make a similar change to SelectFileState.py
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With