I have a piece of code that defines possible item types and enchantment types in a game. Some enchantment types are incompatible with each other or with certain item types. I would like each item type to have information on which enchantments are incompatible with it, as well as have every enchantment contain information about the items it is compatible with, without having to constantly look one of them up.
items.py
:
from enum import Enum, auto
class ItemType(Enum):
PLATE = auto()
HELMET = auto()
BOOTS = auto()
SWORD = auto()
BOW = auto()
# Get compatible enchantment types
from enchantments import EnchantmentType
for it in ItemType:
it.compatible_enchantments = set(filter(lambda ench: it in ench.compatible_items, EnchantmentType))
class Item:
def __init__(self, item_type, enchantments=None):
self.type = item_type
self.enchantments = []
if enchantments:
for ench in enchantments:
self.add_enchantment(ench)
def add_enchantment(self, enchantment, i=None):
if enchantment.type not in self.compatible_enchantments:
raise ValueError(f"Enchantment {enchantment.type} is incompatible with {self.type}.")
if i is None:
self.enchantments.append(enchantment)
else:
self.enchantments.insert(enchantment, i) from enum import Enum
from items import ItemType as IT
enchantments.py
:
from enum import Enum, auto
class EnchantmentType(Enum):
ENHANCED_ARMOUR = IT.HELMET, IT.PLATE, IT.BOOTS, IT.RING
ENHANCED_DAMAGE = IT.SWORD, IT.BOW, IT.RING
YELLOW_COLOUR = ()
def __init__(self, *compatible_item_types):
self.compatible_items = set(IT) if not compatible_item_types else compatible_item_types
self.incompatible_enchantments = set()
# Fill in the incompatible enchantments
for mutualy_exclusive_group in (
{EnchantmentType.ENHANCED_ARMOUR, EnchantmentType.ENHANCED_DAMAGE}
):
for ench in mutualy_exclusive_group:
ench.incompatible_enchantments += mutualy_exclusive_group - {ench}
class Enchantment:
def __init__(self, enchantment_type, level=None):
self.type = enchantment_type
self.level = level
main.py
:
from enchantments import EnchantmentType as ET
print(ET.ENHANCED_ARMOUR.compatible_items)
print(ET.ENHANCED_DAMAGE.compatible_items)
print(ET.YELLOW_COLOUR.compatible_items)
Running this code gives me an ImportError
citing circular imports.
Following this answer I've tried changing the from x import y
statements to import x
but am still getting the same error.
I've temporarily solved the issue by removing from enchantments import EnchantmentType
from items.py
and moving the lines
from enchantments import EnchantmentType
for it in ItemType:
it.compatible_enchantments = set(filter(lambda ench: it in ench.compatible_items, EnchantmentType))
into enchantments.py
. However, this requires that any module that wishes to have correct information about the enchantments manually import enchantments.py
-- importing items.py
only will result in all the compatible_enchantments
being empty.
Is there a way to make my circular imports work without merging the two files?