Мы начинаем новый проект в Python с несколькими запатентованными алгоритмами и чувствительными кусочками логики, которые мы хотели бы сохранить в секрете. У нас также будет несколько аутсайдеров (избранных представителей общественности), работающих над кодом. Мы не можем предоставить посторонним доступ к небольшим частным частям кода, но нам бы хотелось, чтобы общедоступная версия работала достаточно хорошо для них.
Скажем, что в нашем проекте Foo есть модуль bar
с одной функцией get_sauce()
. То, что действительно происходит в get_sauce()
, является секретным, но мы хотим, чтобы общедоступная версия get_sauce()
возвращала приемлемый, хотя и неверный, результат.
У нас также есть собственный сервер Subversion, поэтому мы полностью контролируем, кто и к чему имеет доступ.
Symlinks
Моей первой мыслью была символическая ссылка - вместо bar.py
, предоставьте bar_public.py
всем и bar_private.py
только внутренним разработчикам. К сожалению, создание символических ссылок - это утомительная ручная работа, особенно если в действительности будет около двух десятков таких частных модулей.
Что еще более важно, это затрудняет управление файлом authz Subversion, поскольку для каждого модуля, который мы хотим защитить, на сервере должно быть добавлено исключение. Кто-то может забыть сделать это и случайно проверить секреты ... Тогда модуль находится в репо, и мы должны перестроить репозиторий без него и надеяться, что посторонний не загрузит его в это время.
Несколько хранилищ
Следующая мысль состояла в том, чтобы иметь два хранилища:
private
└── trunk/
├── __init__.py
└── foo/
├── __init__.py
└── bar.py
public
└── trunk/
├── __init__.py
└── foo/
├── __init__.py
├── bar.py
├── baz.py
└── quux.py
Идея состоит в том, что только внутренние разработчики смогут проверять как private/
, так и public/
. Внутренние разработчики установят свои PYTHONPATH=private/trunk:public/trunk
, но все остальные просто установят PYTHONPATH=public/trunk
. Тогда и инсайдеры, и аутсайдеры могут from foo import bar
и получить нужный модуль, верно?
Давайте попробуем это:
% PYTHONPATH=private/trunk:public/trunk python
Python 2.5.1
Type "help", "copyright", "credits" or "license" for more information.
>>> import foo.bar
>>> foo.bar.sauce()
'a private bar'
>>> import foo.quux
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named quux
Я не эксперт по Python, но похоже, что Python уже решил о модуле foo
и ищет по этому поводу:
>>> foo
<module 'foo' from '/path/to/private/trunk/foo/__init__.py'>
Даже удаление foo
помогает:
>>> import sys
>>> del foo
>>> del sys.modules['foo']
>>> import foo.quux
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named quux
Можете ли вы дать мне лучшее решение или предложение?