# -*- coding: UTF-8 -*- ## ##
## ##Процедура py2html() по своему действию противоположна процедуре html2py(). Если html2py() преобразует html-страницы в сценарии Python, превращая html-разметку в комментарии, то py2html() убирает все добавленные комментарии, восстанавливая оформление исходного html-файла.
## ##Процедуры html2py() и py2html() написаны на Python 2. Для их работы нужен дополнительный модуль code_tag.py. ## ##html-файлы со встроенными сценариями Python должны быть оформлены по особым правилам. ## ##Есть четыре варианта запуска процедуры py2html():def code_start1(): ## return '<CODE>' ## ##def code_start2(): ## return '<code>' ## ##def code_end1(): ## return '</CODE>' ## ##def code_end2(): ## return '</code>'## ##В модуле code_tag.py хранятся сочетания символов '<CODE>', '<code>', '</CODE>' и '</code>'. В данном файле они - часть кода Python. Использовать их в явном виде, равно как заменить угловые скобки на символы < и > нельзя: программа будет работать неправильно.
# -*- coding: UTF-8 -*-
# Этот код получен из файла py2html.html с помощью утилиты html2py.py
import code_tag
from Tkinter import *
import tkFileDialog
import tkMessageBox
import os
import StringIO
import webbrowser
##
##
##
#### ##В файле html2py.ini хранится имя последнего сконвертированного и записанного на диск файла; окно выбора файла открывается именно в каталоге этого файла. Если файл html2py.ini по какой-то причине не удается открыть, выбор файла производится из рабочего каталога программы.
## ##Переменная ifile содержит имя файла с расширением *.py, который в последний раз был сохранен утилитой html2py. При каждом сохранении сконвертированного в сценарий Python файла его имя записывается в служебный файл html2py.ini.
##
##Параметр initialdir - название каталога, в котором открывается диалоговое окно; оно соответствует последнему записанному на диск сценарию, обработанному утилитой html2py.py. Функция os.path.split() возвращает кортеж строк, содержащих адрес каталога и имя файла.
##
##
##
def choice():
root=Tk()
root.withdraw()
try:
filedd=open("py2html.ini", "r")
ifile=filedd.readline()
filedd.close()
except IOError:
ifile=""
myfiletypes=[('Файлы Python', '*.py'),('Все файлы', '*')]
filetext=tkFileDialog.Open(title='Запуск...',initialdir=os.path.split(ifile)[0],filetypes=myfiletypes)
return filetext
##
##
##
#### ##Переменная code показывает, содержится ли в данной строке код Python (code=1) или комментарий (code=0)Переключатель switch включает вывод текстовой информации во временный файл a. Пока не появится первый тег <CODE>, ничего выводиться не будет.
## ##a - файл, куда временно записывается генерируемый html-файл.
## ##
def py2html(py_name,file_html,run):
global code
code=0
a = StringIO.StringIO()
if py_name=='':
b=open(choice().show(), 'r')
else:
b=open(py_name,'r')
##
##
##
##Считываем открытый файл по одной строке и суммируем эти строки в переменной b1. Счетчик строк k вводится только по одной причине. Для подключения поддержки русского языка процедура html2.py() всякий раз принудительно вставляет в начало генерируемого сценария строку '# -*- coding: UTF-8 -*-\n'. Поэтому при обратной конвертации сценария в html-файл эту строку нужно удалить. Удаление происходит только в том случае, если эта строка - первая.
b1=''
k=0
for line in b.readlines():
if (k==0) & (line[:23]=='# -*- coding: UTF-8 -*-'):
k=k+1
continue
k=k+1
code_start=0
code_end=0##
##
##Переменная цикла line по очереди ссылается на все строки считываемого файла. Мы будем побайтно перебирать каждую из них в поисках тегов <CODE> и </CODE>. Условия i<(len(b1)-5) и i<(len(b1)-6) нужны, чтобы при проверке мы не вылезали за конец строки. Числа 5 и 6 здесь соответствуют длине строк '<CODE>' и '</CODE>' (+1). Переменная start_tag представляет собой что-то вроде окошечка (см. рисунок), которое посимвольно перемещается по строке слева направо, пока в окошечко не попадет сочетание символов <CODE>. Тогда переключателю code присваивается ненулевое значение (область кода Python), а метке code_start - значение, равное 1 (в строке обнаружен стартовый тег <CODE>).## ##Затем в том же шаге цикла проводится аналогичный поиск тега </CODE>. Если он обнаруживается, меняются значения переменных code и code_end, и удаляется значок "##", стоящий перед этим тегом. Строка line разбивается на две части методом split(); границей раздела является комбинация символов </CODE>.
##
##
##
##Условие if (start_tag==code_tag.code_start1()) | (start_tag==code_tag.code_start2()): идентично условию if (start_tag=='<CODE>') | (start_tag=='<code>'): и if (end_tag==code_tag.code_end1()) | (end_tag==code_tag.code_end2()): идентично if (end_tag=='</CODE>') | (end_tag=='</code>'):. Здесь теги <CODE> и </CODE> - часть кода Python, и заменить угловые скобки на их символические обозначения (< и >) нельзя. Поэтому код Python, где явно присутствуют сочетания символов <CODE> и </CODE>, вынесен за пределы этого файла в отдельный модуль code_tag.py.
##
##
##
##
for i in range(len(line)):
if (i<(len(line)-5)):
start_tag=line[i]+line[i+1]+line[i+2]+line[i+3]+line[i+4]+line[i+5]
if (start_tag==code_tag.code_start1()) | (start_tag==code_tag.code_start2()):
code=1
code_start=1
if (i<(len(line)-6)):
end_tag=line[i]+line[i+1]+line[i+2]+line[i+3]+line[i+4]+line[i+5]+line[i+6]
if (end_tag==code_tag.code_end1()) | (end_tag==code_tag.code_end2()):
code=0
code_end=1
line1=line.split(end_tag)[0]
line2=line.split(end_tag)[1]
if (line1[-1]+line1[-2])=='##':
line1=line1[:-2]
line=line1+end_tag+line2
break##
##
##В зависимости от результатов поиска тегов <CODE> и </CODE> рассматриваемая строка или приплюсовывается к строке b1 без изменений, или, если строка не относится к зоне действия тега <CODE>, после проверки из ее начала удаляются символы "##". После того как в цикле будут обработаны все строки файла, итоговая строковая переменная b1 записывается во временный файл a.
##
##
if (code_end==0):
if (code==0) ^ (code_start==1):
if (line[0]+line[1])=='##':
line=line[2:]
b1=b1+line
a.write(b1)##
##
##В переменной dir_file хранится имя директории, в которой находится обрабатываемый сценарий Python и куда будет записан сгенерированный из него html-файл.
##
##Если файл с расширением .html создавать нужно (if file_html!=0:), то, прежде всего нужно заменить расширение исходного файла с .py на .html. Новое имя файла определяется выражением file_title[0]+'/'+name_html[0]+'.html'. Если файл с таким названием уже существует, то надо спросить, перезаписывать его или нет, с помощью функции tkMessageBox.askquestion().
##
##
dir_file=os.path.split(b.name)[0]
if file_html!=0:
file_title=os.path.split(b.name)
name_html=file_title[1].split(".")
if os.path.isfile(file_title[0]+'/'+name_html[0]+'.html')!=0:
if tkMessageBox.askquestion("Сохранить как",\
file_title[0]+'/'+name_html[0]+'.html'+ u' уже существует. Заменить?')=="yes":##
##
##
##Содержимое полученного html-файла можно вызвать с помощью команды a.getvalue(). Кроме перезаписи существующего html-файла нужно еще записать название обрабатываемого сценария Python во вспомогательный ini-файл. Если полученный html-файл нужно запустить (if run!=0:), выводим его в веб-браузер с помощью команды webbrowser.open_new_tab(filew.name).
ini_file=open("py2html.ini","w")
ini_file.write(b.name)
ini_file.close()
open(file_title[0]+'/'+name_html[0]+'.html','w').write(a.getvalue())
if run!=0:
filew=open(file_title[0]+'/'+name_html[0]+'.html', "r")
webbrowser.open_new_tab(filew.name)
filew.close()
else:
pass
else:
pass##
##
##Если файла с таким именем нет, создаем его без лишних вопросов, не забывая прежде записать его имя во вспомогательный ini-файл. Если полученный html-файл нужно запустить (if run!=0:), выводим его в веб-браузер.
else:
ini_file=open("py2html.ini","w")
ini_file.write(b.name)
ini_file.close()
open(file_title[0]+'/'+name_html[0]+'.html','w').write(a.getvalue())
if run!=0:
filew=open(file_title[0]+'/'+name_html[0]+'.html', "r")
webbrowser.open_new_tab(filew.name)
filew.close()
else:
pass##
##
##
##Если файл с расширением .html создавать не требуется, то никакие дальнейшие действия не производятся.
else:
pass
a.close()
if __name__ == '__main__':
py2html('',1,1)
##
##
##
####
## ##Данный html-файл содержит в себе сценарий Python, который может быть извлечен и/или запущен на выполнение с помощью утилиты html2py.py.
##
##Автор: Филипп Занько
##
##Web-адрес: http://www.russianlutheran.org/python/python.html
##
##Лицензия: Creative Commons Attribution-ShareAlike 3.0 Unported License
##
##
##О своих предложениях, замеченных ошибках, неточностях, опечатках просьба сообщать по электронному адресу:
russianlutheran@gmail.com
##
##