SciPy состоит из пакетов Python, называемых пакетами SciPy, которые доступны пользователям Python через scipy пространство имён. Каждый пакет SciPy
может содержать другие пакеты SciPy. И так далее. Поэтому дерево каталогов SciPy
представляет собой дерево пакетов с произвольной глубиной и шириной.
Любой пакет SciPy может зависеть от пакетов NumPy, но зависимость от других
пакетов SciPy должна быть минимальной или нулевой.
Пакет SciPy содержит, в дополнение к своим исходным файлам, следующие файлы и директории:
Чтобы добавить пакет Python в SciPy, его скрипт сборки (setup.py)
должен соответствовать определённым требованиям. Наиболее важное требование — чтобы
пакет определял configuration(parent_package='',top_path=None) функция
которая возвращает словарь, подходящий для передачи в
numpy.distutils.core.setup(..). Чтобы упростить построение
этого словаря, numpy.distutils.misc_util предоставляет
Configuration класс, описанный ниже.
Аргументы configuration функция указывает имя родительского пакета SciPy (parent_package) и расположение каталога
основного setup.py скрипт (top_path). Эти аргументы, вместе с именем текущего пакета, должны быть переданы в
Configuration конструктор.
The Configuration конструктор имеет четвертый необязательный аргумент,
package_path, который можно использовать, когда файлы пакета расположены в
другом месте, чем каталог setup.py файл.
Оставшиеся Configuration аргументы — это все именованные аргументы, которые будут
использованы для инициализации атрибутов Configuration
экземпляра. Обычно эти ключевые слова совпадают с теми, которые
setup(..) функция ожидает, например, packages,
ext_modules, data_files, include_dirs, libraries,
headers, scripts, package_dir, и т.д. Однако прямое
указание этих ключевых слов не рекомендуется, так как содержимое
этих аргументов ключевых слов не будет обработано или проверено на
согласованность системы сборки SciPy.
Наконец, Configuration имеет .todict() метод, который возвращает все данные конфигурации в виде словаря, подходящего для передачи в
setup(..) функция.
В дополнение к атрибутам, которые можно указать через ключевые аргументы
в Configuration конструктор, Configuration экземпляре (обозначим как config) имеет следующие атрибуты, которые могут быть полезны при написании скриптов настройки:
config.name - полное имя текущего пакета. Имена родительских
пакетов могут быть извлечены как config.name.split('.').
config.local_path - путь к текущему местоположению setup.py файл.
config.top_path - путь к местоположению main setup.py файл.
config.todict() — возвращает словарь конфигурации, подходящий для
передачи в numpy.distutils.core.setup(..) функция.
config.paths(*paths)---applies``glob.glob(..) к элементам
paths при необходимости. Исправляет paths элемент, который относится к
config.local_path.
config.get_subpackage(subpackage_name,subpackage_path=None) — возвращает список конфигураций подпакетов. Подпакет ищется в текущем каталоге под именем subpackage_name но путь также может быть указан через необязательный subpackage_path аргумент.
Если subpackage_name указывается как None тогда имя подпакета
будет взято из базового имени subpackage_path.
Любой * используемые для имён подпакетов, расширяются как подстановочные знаки.
config.add_subpackage(subpackage_name,subpackage_path=None) —
добавить конфигурацию подпакета SciPy к текущей. Значение
и использование аргументов объяснено выше, см.
config.get_subpackage() метод.
config.add_data_files(*files) — добавить в начало files to data_files
список. Если files элемент является кортежем, то его первый элемент определяет
суффикс, куда копируются файлы данных относительно каталога установки пакета,
а второй элемент указывает путь к файлам
данных. По умолчанию файлы данных копируются в каталог установки пакета. Например,
Путь к файлам данных может быть функцией, не принимающей аргументов и возвращающей путь(и) к файлам данных — это полезно, когда файлы данных генерируются во время сборки пакета. (XXX: объяснить шаг, когда эта функция вызывается точно)
config.add_data_dir(data_path) — добавить каталог data_path
рекурсивно к data_files. Все дерево каталогов, начиная с
data_path будет скопирован в каталог установки пакета.
Если data_path является кортежем, то его первый элемент определяет
суффикс, куда копируются файлы данных относительно каталога установки пакета,
а второй элемент указывает путь к каталогу данных.
По умолчанию каталог данных копируется в каталог установки пакета
под базовым именем data_path. Например,
config.add_include_dirs(*paths) — добавить в начало paths to
include_dirs list. Этот список будет виден всем расширяющим
модулям текущего пакета.
config.add_headers(*files) — добавить в начало files to headers
список. По умолчанию заголовки будут установлены в
/include/pythonX.X//
каталог. Если files элемент является кортежем, то его первый аргумент
определяет суффикс установки относительно
/include/pythonX.X/ путь. Это метод Python distutils;
его использование не рекомендуется для NumPy и SciPy в пользу
config.add_data_files(*files).
config.add_scripts(*files) — добавить в начало files to scripts
список. Скрипты будут установлены под /bin/ каталог.
config.add_extension(name,sources,**kw) — создать и добавить
Extension экземпляр для ext_modules список. Первый аргумент
name определяет имя модуля расширения, который будет установлен под config.name пакет. Второй аргумент —
список источников. add_extension метод также принимает ключевые аргументы, которые передаются в Extension конструктор. Список разрешенных ключевых слов следующий: include_dirs,
define_macros, undef_macros, library_dirs, libraries,
runtime_library_dirs, extra_objects, extra_compile_args,
extra_link_args, export_symbols, swig_opts, depends,
language, f2py_options, module_dirs, extra_info,
extra_f77_compile_args, extra_f90_compile_args.
Обратите внимание, что config.paths метод применяется ко всем спискам,
которые могут содержать пути. extra_info является словарём или списком словарей, содержимое которого будет добавлено к именованным аргументам.
Список depends содержит пути к файлам или каталогам, от которых зависят исходные коды модуля расширения. Если любой путь в depends список новее, чем модуль расширения, то модуль будет пересобран.
Список источников может содержать функции ('генераторы источников') с шаблоном def(ext,build_dir):returnorNone>. Если funcname возвращает None, источники не генерируются. И если Extension экземпляр не имеет источников после обработки всех генераторов источников, расширение не будет построено. Это рекомендуемый способ условного определения модулей расширения. Функции генераторов источников вызываются
build_src подкоманда numpy.distutils.
Например, вот типичная функция-генератор источника:
Первый аргумент содержит экземпляр Extension, который может быть
полезен для доступа к его атрибутам, таким как depends, sources, и т.д. списки и изменяют их в процессе сборки.
Второй аргумент указывает путь к каталогу сборки, который должен использоваться при создании файлов на диске.
config.add_library(name,sources,**build_info) — добавить
библиотеку в libraries список. Допустимые аргументы ключевых слов:
depends, macros, include_dirs, extra_compiler_args,
f2py_options, extra_f77_compile_args,
extra_f90_compile_args. См. .add_extension() метод для получения дополнительной информации об аргументах.
config.have_f77c() — возвращает True, если компилятор Fortran 77
доступен (читай: простой код Fortran 77 успешно скомпилирован).
config.have_f90c() — возвращает True, если компилятор Fortran 90 доступен (читай: простой код Fortran 90 успешно скомпилирован).
config.get_version() — возвращает строку версии текущего пакета,
None если информацию о версии не удалось определить. Этот метод сканирует файлы __version__.py, _version.py,
version.py, __svn_version__.py для строковых переменных
version, __version__, _version.
config.make_svn_version_py() — добавляет функцию данных к
data_files список, который сгенерирует __svn_version__.py файл
в текущий каталог пакета. Файл будет удален из
исходного каталога при выходе из Python.
config.get_build_temp_dir() — возвращает путь к временному
каталогу. Это место, где следует создавать временные
файлы.
config.get_distribution() — вернуть distutils Distribution
экземпляр.
config.get_config_cmd() — возвращает numpy.distutils экземпляр команды config.
config.get_info(*names) —
Преобразование .src файлы с использованием шаблонов#
NumPy distutils поддерживает автоматическое преобразование исходных файлов с именем .src. Эта возможность может использоваться для поддержания очень похожих блоков кода, требующих лишь простых изменений между блоками. На этапе сборки setup, если встречается файл-шаблон с именем .src, новый файл с именем создаётся из шаблона и помещается в директорию сборки для использования вместо него. Поддерживаются две формы преобразования шаблонов. Первая форма применяется для файлов с именем .ext.src, где ext - распознаваемое расширение Fortran (f, f90, f95, f77, for, ftn, pyf). Вторая форма используется для всех остальных случаев.
Этот шаблонный конвертер будет реплицировать все функция и
подпрограмма блоки в файле с именами, содержащими ‘<…>’ согласно правилам в ‘<…>’. Количество слов, разделенных запятыми, в ‘<…>’ определяет, сколько раз блок повторяется. Значение этих слов указывает, на что должно быть заменено это правило повторения ‘<…>’ в каждом блоке. Все правила повторения в блоке должны содержать одинаковое количество слов, разделенных запятыми, указывающее, сколько раз блок должен повторяться. Если слово в правиле повторения требует запятой, левой или правой стрелки, то перед ним ставится обратная косая черта ‘ '. Если слово в правиле повторения совпадает с ‘ \’, то оно будет заменено на -е слово в той же спецификации повторения. Существует две формы правила повторения: именованная и краткая.
Именованное правило повторения полезно, когда один и тот же набор повторений должен использоваться несколько раз в блоке. Оно задаётся с помощью , где N — количество раз, которое блок должен быть повторён. При каждом повторении блока всё выражение ‘<…>’ будет сначала заменено на item1, затем на item2 и так далее, пока не будет выполнено N повторений. После введения именованной спецификации повторения то же правило повторения может быть использовано в текущем блоке путем ссылки только на имя (т.е. ).
Краткое правило повторения выглядит как <элемент1, элемент2, элемент3, …, элементN>. Правило указывает, что всё выражение '<…>' должно быть заменено сначала на элемент1, затем на элемент2 и так далее, пока не будет выполнено N повторений.
Не-фортран файлы используют отдельный синтаксис для определения блоков шаблонов,
которые должны повторяться с использованием расширения переменных, аналогичного
именованным правилам повторения для фортран-специфичных повторов.
NumPy Distutils предварительно обрабатывает исходные файлы C (расширение: .c.src) написанный на пользовательском языке шаблонов для генерации C-кода. The @ символ используется для обертывания макроподобных переменных, чтобы обеспечить механизм подстановки строк, который может описывать (например) набор типов данных.
Блоки языка шаблонов ограничены /**beginrepeat
и /**endrepeat**/ строки, которые также могут быть вложенными с использованием
последовательно нумерованных разделительных строк, таких как /**beginrepeat1
и /**endrepeat1**/:
/**beginrepeat на отдельной строке отмечает начало
сегмента, который должен быть повторен.
Именованные расширения переменных определяются с помощью #name=item1,item2,item3,...,itemN# и размещаются на последовательных строках. Эти переменные заменяются в каждом блоке повтора соответствующим словом. Все именованные переменные в том же блоке повтора должны определять одинаковое количество слов.
При указании правила повторения для именованной переменной, item*N является сокращением для item,item,...,item повторяется N раз. Кроме того, скобки в сочетании с *N может использоваться для группировки нескольких элементов, которые должны повторяться. Таким образом, #name=(item1,item2)*4# эквивалентно #name=item1,item2,item1,item2,item1,item2,item1,item2#.
*/ на отдельной строке отмечает конец именования расширения переменной. Следующая строка — первая строка, которая будет повторена с использованием именованных правил.
Внутри блока, который нужно повторить, переменные, которые должны быть расширены,
указываются как @name@.
/**endrepeat**/ на отдельной строке отмечает предыдущую строку как последнюю строку блока для повторения.
Цикл в исходном коде NumPy на C может иметь @TYPE@ переменная, предназначенная для подстановки строк, которая предварительно обрабатывается в несколько иначе идентичных циклов с несколькими строками, такими как INT, LONG, UINT,
ULONG. @TYPE@ синтаксис стиля таким образом уменьшает дублирование кода и нагрузку на поддержку, имитируя языки с поддержкой обобщённых типов.
Вышеуказанные правила могут быть понятнее в следующем примере исходного шаблона:
Предварительная обработка файлов исходного кода на языке C с обобщенными типами (как в самом NumPy, так и в любом стороннем пакете, использующем NumPy Distutils) выполняется conv_template.py.
Сгенерированные специфичные для типа C-файлы (расширение: .c)
этими модулями в процессе сборки готовы к компиляции. Эта
форма обобщённой типизации также поддерживается для заголовочных файлов C (предобработанных
для создания .h файлы).
get_numpy_include_dirs() — возвращает список базовых
директорий с заголовочными файлами NumPy. Базовые директории с заголовочными файлами NumPy содержат
файлы заголовков, такие как numpy/arrayobject.h, numpy/funcobject.h
и т.д. Для установленного NumPy возвращаемый список имеет длину 1,
но при сборке NumPy список может содержать больше директорий,
например, путь к config.h файл, который
numpy/base/setup.py файл генерируется и используется numpy
заголовочные файлы.
append_path(prefix,path) — умное добавление path to prefix.
gpaths(paths,local_path='') — применить glob к путям и добавить префикс
local_path при необходимости.
njoin(*path) — объединить компоненты пути + преобразовать /-разделенный путь
к os.sep-разделенный путь и разрешить .., . из путей.
Например, njoin('a',['b','./c'],'..','g')->os.path.join('a','b','g').
minrelpath(path) — разрешает точки в path.
rel_path(path,parent_path) — возвращает path относительно parent_path.
defget_cmd(cmdname,_cache={}) — возвращает numpy.distutils
экземпляр команды.
get_path(mod_name,parent_path=None) — возвращает путь модуля относительно parent_path, если он задан. Также обрабатывает __main__ и
__builtin__ модули.
"""Package docstring, typically with a brief description and function listing."""# import functions into module namespacefrom.subpackageimport*...__all__=[sforsindir()ifnots.startswith('_')]fromnumpy.testingimportTestertest=Tester().testbench=Tester().bench
скомпилирует library исходных кодов без флагов оптимизации.
Рекомендуется указывать только те опции config_fc таким образом, чтобы они были независимы от компилятора.
Получение дополнительных опций компилятора Fortran 77 из исходного кода#
Некоторым старым кодам на Fortran требуются специальные опции компилятора для корректной работы. Чтобы указать опции компилятора для каждого исходного файла, numpy.distutils Компилятор Fortran ищет следующий
шаблон:
CF77FLAGS(<fcompilertype>)=<fcompilerf77flags>
в первых 20 строках исходного кода и использовать f77flags для указанного типа fcompiler (первый символ C является необязательным).
TODO: Эта функция может быть легко расширена для кодов Fortran 90
тоже. Сообщите нам, если вам нужна такая функция.