Уведомления

Группа в Telegram: @pythonsu

#1 Май 25, 2010 14:15:45

ZZZ
От: Москва
Зарегистрирован: 2008-04-03
Сообщения: 2161
Репутация: +  26  -
Профиль   Адрес электронной почты  

Наследование конфигов

Привет всем!

Никогда не думал, что столкнусь такой проблемой, но вот, столкнулся.
Есть проект на джанге и к ней три связанных (наследуемых?) конфигов.

settings.py опустим за ненадобностью – в нём храниться только то, что касается самой джанги;
config.py – центральный конфиг содержащий дефолтные значения;
local_config.py – локальный конфиг конкретного экземпляра проекта (не попадает под версионирование).

Идея в том, чтобы переопределять значения config.py значениями из local_config.py. Это нужно, например, для запуска нескольких разработческих хостов… В общем очень удобно.
Вот только организованно странно.

Вот кусочек config.py:

import sys 

# Вот такая конструкция...
from local_config import *
__current_dict = sys.modules[__name__].__dict__
s = lambda x, y: __current_dict.setdefault(x, y)

# Вот такой пример использования...

s('WEB_SERVER_IP', '192.168.13.6') # None in case of dynamic IPs or specific address (string)
s('WEB_SERVER_PORT', None) # str
if WEB_SERVER_IP and WEB_SERVER_IP:
if WEB_SERVER_PORT and WEB_SERVER_PORT:
NGINX_LISTEN_DIRECTIVE_ATTRIBUTE = WEB_SERVER_IP + ':' + WEB_SERVER_PORT
else:
NGINX_LISTEN_DIRECTIVE_ATTRIBUTE = WEB_SERVER_IP
else:
NGINX_LISTEN_DIRECTIVE_ATTRIBUTE = WEB_SERVER_PORT
Весь прикол в том, что config.py может использовать переменные из local_config.py, а не просто переопределять свои.

Собственно оно работает и, в общем-то, не плохо. Меня интересует, как можно сделать этот конфиг более наглядным.
Есть ли у кого-нить мысли по этому поводу?

P.S. За код не пинайте, он не мой.



Отредактировано (Май 25, 2010 14:19:18)

Офлайн

#2 Май 25, 2010 15:15:15

Evg
От:
Зарегистрирован: 2008-12-25
Сообщения: 346
Репутация: +  -1  -
Профиль   Отправить e-mail  

Наследование конфигов

Убрать всю мутотень с лямбдой? и просто поставить from local_config import * после объявления значений?

WEB_SERVER_IP =  '192.168.13.6'
...
from local_config import *



Офлайн

#3 Май 25, 2010 15:41:09

ZZZ
От: Москва
Зарегистрирован: 2008-04-03
Сообщения: 2161
Репутация: +  26  -
Профиль   Адрес электронной почты  

Наследование конфигов

:-) Если бы всё было так просто…
Это была моя первая мысль, которая с треском разбилась об желание “некоторых” иметь возможность вычислить нужное значение в процессе работы config.py.
Я немного не полностью раскрыл тему.

import sys 

from local_config import *
__current_dict = sys.modules[__name__].__dict__
s = lambda x, y: __current_dict.setdefault(x, y)

s('VAR1', 1)

VAR2 = VAR1 + 1
Если в local_config.py будет “VAR1 = 10” и будет отсутствовать VAR2, то VAR2 станет равен 11. В твоём же случае будет 2.
Это довольно принципиальный момент.



Офлайн

#4 Май 25, 2010 16:05:11

Evg
От:
Зарегистрирован: 2008-12-25
Сообщения: 346
Репутация: +  -1  -
Профиль   Отправить e-mail  

Наследование конфигов

Почему это?)
l_set.py:

VAR1 = 10
set.py:
VAR1 = 1
from l_set import VAR1
VAR2 = VAR1 + 1
print VAR2 # 11 а не 2



Офлайн

#5 Май 25, 2010 16:15:01

Александр Кошелев
От: Москва
Зарегистрирован: 2007-02-03
Сообщения: 1724
Репутация: +  2  -
Профиль   Отправить e-mail  

Наследование конфигов

ZZZ
Весь прикол в том, что config.py может использовать переменные из local_config.py, а не просто переопределять свои.
Он не должен этого хотеть. Вы пытаетесь реализовать (или поддержать?) систему которая порочна изначально по сути. Лучше пересмотреть её целиком.



Офлайн

#6 Май 25, 2010 16:35:37

ZZZ
От: Москва
Зарегистрирован: 2008-04-03
Сообщения: 2161
Репутация: +  26  -
Профиль   Адрес электронной почты  

Наследование конфигов

Evg
Почему это?)
Потому что в l_set.py может и не быть VAR1 и тогда мы получим ImportError, что явно не согласуется с требуемым результатом.
Ещё добавлю, что это уже совсем сложно – две строки на параметр, не очень красиво.

Daevaorn
Вы пытаетесь реализовать (или поддержать?) систему которая порочна изначально по сути. Лучше пересмотреть её целиком.
Полностью с тобой согласен, но не мне это решать. Я лишь пытаюсь её более красиво реорганизовать.
С другой же стороны, у этой схемы есть и плюсы. Такие переменные, как, например, пути, вполне могут зависеть друг от друга.

Я думал, может вынести всё это на уровень класса… Но так ничего и не придумал.



Офлайн

#7 Май 25, 2010 16:45:31

Evg
От:
Зарегистрирован: 2008-12-25
Сообщения: 346
Репутация: +  -1  -
Профиль   Отправить e-mail  

Наследование конфигов

ZZZ
Потому что в l_set.py может и не быть VAR1 и тогда мы получим ImportError, что явно не согласуется с требуемым результатом.
Ну так это совсем просто решается:
from l_set import *
Еще можно обернуть в try except на случай отсутсвия файла.

ZZZ
Ещё добавлю, что это уже совсем сложно – две строки на параметр, не очень красиво.
Не понял какие 2 строки?



Офлайн

#8 Май 25, 2010 18:00:06

ZZZ
От: Москва
Зарегистрирован: 2008-04-03
Сообщения: 2161
Репутация: +  26  -
Профиль   Адрес электронной почты  

Наследование конфигов

Evg, посмотри на поведение моего предыдущего кода.

Сначала мы делаем from local_config.py import *.
Потом смотрим, определена ли VAR1 иБ если не определена, определяем дефолтным значением.
Ну и дальше используем уже точно определённую VAR1 для вычисления VAR2.

В твоём же случае, между определением дефолтного значения и использованием VAR1 нужно попытаться переопределить его из local_config. Это совсем не красиво и… Параметров там тьма! И все в гробах! (с)

Пока я думаю о том, чтобы дефолтные параметры вынести в нормальном виде куда-нить в config_defaults.py, а в config.py положить логику совмещения локального и дефолтного конфигов.
Как вам такая мысль?



Офлайн

#9 Май 25, 2010 23:48:25

poltergeist
От:
Зарегистрирован: 2007-02-28
Сообщения: 522
Репутация: +  0  -
Профиль   Отправить e-mail  

Наследование конфигов

class Setting(object):

def __init__(self, value):
self._value = value

def __call__(self):
if callable(self._value):
return self._value()
return self._value


WEB_SERVER_IP = Setting('192.168.13.6')
WEB_SERVER_PORT = Setting(80)

@Setting
def NGINX_LISTEN_DIRECTIVE_ATTRIBUTE():
ip, port = WEB_SERVER_IP(), WEB_SERVER_PORT()
return '%s:%s' % (ip, port) if ip and port else ip or port

#try:
# from local_settings import *
#except ImportError:
# pass
# override some settings from local_settings
WEB_SERVER_PORT = Setting(8080)


settings = {}
for key, value in globals().items():
if isinstance(value, Setting):
settings[key] = value()

print settings
Output:
{'NGINX_LISTEN_DIRECTIVE_ATTRIBUTE': '192.168.13.6:8080', 'WEB_SERVER_PORT': 8080, 'WEB_SERVER_IP': '192.168.13.6'}
А вообще да, вы сами себе геморрой придумали своими хотениями. Вот умеют же люди из простой джанги монстров делать по своему хотению:) Всем обычно хватает from local_settings.py import *, а всё то, что вы пытаетесь вычислить - этому не место в settings-ах, это в коде приложения расчитывается на основе сеттингсов.



Отредактировано (Май 25, 2010 23:59:33)

Офлайн

#10 Май 26, 2010 10:49:12

ZZZ
От: Москва
Зарегистрирован: 2008-04-03
Сообщения: 2161
Репутация: +  26  -
Профиль   Адрес электронной почты  

Наследование конфигов

poltergeist
А вообще да, вы сами себе геморрой придумали своими хотениями. Вот умеют же люди из простой джанги монстров делать по своему хотению :-) Всем обычно хватает from local_settings.py import *, а всё то, что вы пытаетесь вычислить - этому не место в settings-ах, это в коде приложения расчитывается на основе сеттингсов.
Да тут вообще полный п… плохо всё.
Архитектура у проекта просто дебильная! Нет даже нормальной структуры папок – считается большой фишкой то, что все пути прописаны в конфиге и “красиво” переопределяются… Я просто плачу…
Ну да ладно, не мне менять устоявшийся порядок… Я и так тут шухера навёл… :-)

Твой вариант, poltergeist, тоже не особо хорош – шило на мыло менять тоже не особо-то хочется. :-(

Ладно, вопрос считаю закрытым за бесперспективностью.

P.S. И всё-таки это не я дурак, что ничего придумать не смог…



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version