typus — локальний друкар на python

,"`.._ ,"`.
:,--._:)\,:,._,.: Glory to All
:`--," :`...';\ the HYPNO TOAD!
`,' `---' `.
/ :
/ \
,' :\.___,-.
`...,---"```-..._ |: \
( ) ;: ) \ _,-.
`. ( // ` \
: `.// ) ) , ;
,-|`. _,'/ ) ) ,' ,'
( :`.`-..____..=:.-': . _,' ,'
`,'\ `--....-)=' `._, \ ,') _ "`._
_.-/ _ `. (_) / )' ; / \ \`-.'
`--( `-:`. ` ___..' _,-' |/ `.)
`-. `.`.`-----`--, .'
|/`.\` ,','); SSt
` (/ (/

Знайдено в інтернеті.
Всім привіт!
Хочу поділитися своєю невеликою розробкою: друкарем, який можна використовувати локально.
Дисклеймер
Проект знаходиться в стадії розробки і потребує ретельному тестуванні.
Можливості
  • заміна лапок
    """"
    та
    """
    (в англійській версії). Число рівнів не обмежена — типограф просто чергує парні/непарні — де-які можна налаштувати
  • розстановка дюймів, апострофів:
    4'
    ,
    20"
  • комплексні символи: три крапки, копірайти, трейдмарки, стрілочки і т. д.:
    ©
    стає `, причому, навіть якщо написано кирилицею
  • заміна дефісів на довге тире в текстах і числових діапазонах
  • заміна дефісів на коротке тире в номерах телефонів
  • розстановка мінусів і знаків множення
  • зв'язування чисел з наступними словами нерозривним дефісом, наприклад
    40 папуг
  • зв'язування спілок і будь-яких слів з 1-2 символів з наступними словами
  • відділення одиниць вимірювання від чисел (можливо, выпилю в недалекому майбутньому, дуже великий шанс хибно-позитивного результату)
  • нерозривні пробіли в скороченнях:
    т. д.
    стане
    т. д.
    ;
    А. С. Пушкін
    — тут звичайний пробіл стане розривним
  • заміна
    р
    та
    руб
    (з крапкою в кінці і без) на символ рубля — можливо выпилю, оскільки удилит точку якщо знайде збіг в кінці речення
  • заміна дробів
    1/2
    ,
    1/3
    і т. д. на існуючі символи unicode
  • видалення зайвих пробілів і переносів рядків, тримінг спочатку і вкінці
  • розстановка нерозривних пробілів в купі випадків
  • не впливає на html теги і ігнорує вміст
    (head|iframe|pre|code|script|style)
  • можна передати рядки, які друкар буде ігнорувати
Приклади:
from typus import ru_typus

ru_typus('00" "11 \'22\' 11"? "11 \'22 "33 33?"\' 11" 00 "11 \'22\' 11" 0"')
'00" "11 "22" 11"? «11 „22 «33 33?»“ 11" 00 "11 "22" 11" 0"'

Число — рівень вкладеності. Якщо б перша лапки стояла б до нулів, був би ще один рівень, а так вийшли дюйми.
Як влаштований
class BaseTypus(EnRuExpressions, TypusCore):
processors = (EscapePhrases, EscapeHtml, TypoQuotes, Expressions)

class RuTypus(RuQuotes, BaseTypus):
pass

ru_typus = RuTypus()

Typus складається з "процесорів" і "виразів".
Виразу
Це пари
(regex, replace)
, які передаються в
re.sub(regex, replace)
і виконуються послідовно (див. нижче). Майже весь друкар — це "вираження". Вони записуються як методи з приставкою
expr_
, функція повинна повернути вкладений список, тобто одне "вираз" може повернути низку "виразів":
class MyTypus(Typus):
expressions = Typus.expressions + 'http://bar'

def expr_http://bar(self):
expr = (
(r'\d', '@'), # замінює числа @
)
return expr

Третій, необов'язковий аргумент — прапори передаються
re.compile
, за замовчуванням, це
re.I | re.U | re.M | re.S
.
До речі,
replace
може бути функцією, див. re.sub.
Щоб визначити послідовність використовується атрибут друкаря —
expressions
, який зберігає список назв виразів. Можна вимкнути зайве:
from typus import RuTypus

exclude_expressions = ('ruble', 'math')

class MyTypus(RuTypus):
expressions = (e for e in RuTypus.expressions
if e not in exclude_expressions)

expressions
може бути генератором, але якщо зробити послідовністю, можна робити так:
def expr_http://bar(self):
if 'some' in self.expressions:
return baz
return egg

В коробці йде лише один мікс виразів —
EnRuExpressions
, але він робить майже всю роботу.
Для роботи виразів використовується процесор
Expressions
.
Процесори
Іноді простими регулярками не відбутися, доводиться городити убер-функцію. Процесор це клас-функція-декоратор, який ініціюється під час створення типографа, а потім викликається при обробці тексту. Йому (инстансу процесора) передається сам інстанси друкаря, щоб процесор міг отримати доступ до його конфігурації.
При використанні декількох процесорів, вони декорують один одного по черзі. Наприклад, так:
видалити html теги
дати хід наступного процесору, якщо зійшлися зірки
щось там зробити з текстом
обробити і повернути нагору
повернути теги

З Typus поставляються кілька процесорів:
EscapePhrases
,
EscapeHtml
,
TypoQuotes
,
Expressions
.

EscapePhrases

Бувають випадки, коли певний шматок тексту обробляти не можна, або ви заздалегідь знаєте, що друкар на цьому місці затнеться, в такому випадку можна поступити так:
typus('"http://bar 2""', escape_phrases=['2"'])
'«http://bar 2"»'

Без цього друкар зустріне закриває лапки:
«http://bar 2»"
. Ще приклад:
typus('Друкар замінює © ©', escape_phrases=['замінює ©'])
'Друкар замінює © '

Аргумент
escape_phrases
можна винести окремим полем у ваше CRUD додаток (ака "адмінку"), де контент менеджер зможе перерахувати фрази через роздільник, а ви передасте їх типографу.
Щоб розділити текст можна скористатися утилітою:
from typus.utils import splinter

split = splinter(',')
split('a, b,c ') == ['a', 'b', 'c']
split('a, b\,c') == ['a', 'b,c']

splinter
розуміє екрановані роздільники і викликає
str.strip()
для кожної фрази.

EscapeHtml

Выразет html-теги до друкаря і повертає їх після. Без нього
<img src="http://bar">
перетвориться на
<img src=«http://bar»>
.

TypoQuotes

Проставляє лапки. Очікує, що в типографе будуть перераховані атрибути
loq
,
roq
,
leq
,
req
. Приклад:
from typus import BaseTypus
from typus.chars import LAQUO, RAQUO, DLQUO, LDQUO

class MyTypus(BaseTypus):
# Ліва непарна, права непарна, ліва парна, права парна
loq, roq, leq, req = LAQUO, RAQUO, DLQUO, LDQUO

Є готові міксини
EnQuotes
та
RuQuotes
в модулі
typus.mixins
.

Expressions

Забезпечує роботу виразів. Під час ініціалізації типографа всі регулярки створюються і зберігаються у инстансе процесора.

Про налагодження

Якщо типографу передати
debug=True
, то він замінить всі нерозривні пробіли на символ підкреслення, це може бути корисним для налагодження:
ru_typus('© me', debug=True)
'_me'

Демо
Важливо: демо крутиться на дуже простий виртуалке і призначений для демонстрації можливостей.
Я нічого нікуди не збережу (чесно), вихідний код сайту ви знайдете у мене на гітхабі.
Установка і використання
pip install -e git://github.com/byashimov/typus.git#egg=typus

Далі:
from typus import en_typus, ru_typus

en_typus('"Beautiful is better than ugly." © Tim Peters.', debug=True)
'"Beautiful is_better than ugly." _Tim Peters.' # _ for nbsp

ru_typus('"Красиве краще, ніж потворне." © Тім Петерс.')
'«Красиве краще, ніж потворне.» Тім Петерс.' # cyrillic ',' in '(з)'

Документація
Цю статтю можна вважати такою, поки я не зроблю корявий переклад на англійську.
Сумісність
Name Stmts Miss Cover
-----------------------------------------
typus/__init__.py 8 0 100%
typus/chars.py 18 0 100%
typus/core.py 24 0 100%
typus/mixins.py 77 0 100%
typus/processors.py 99 0 100%
typus/utils.py 30 0 100%
-----------------------------------------
TOTAL 256 0 100%
________________ summary ________________
py25: commands succeeded
py26: commands succeeded
py27: commands succeeded
py33: commands succeeded
py34: commands succeeded
py35: commands succeeded
congratulations :)

Travis-CI, яким я користуюся, не підтримує
2.5
, а вручну я перевіряти не завжди працюю, так що якщо ви ще їм користуєтеся (співчуваю), запустіть тести після установки.
Сторінка проекту.
Плани і якісь ідеї
  • Я не планую вносити в типограф підкреслення посилань або розміщення html-тегів. Цим повинен займати процесор текстів (markdown, retext тощо). До того ж, у всіх свої кейси.
  • Я також не хотів би, щоб друкар виправляв помилки в тексті, навіть якщо це нічого не варто.
  • Майже всі друкарі конвертують небезпечні символи, такі як
    &
    , в html-сутності. На даний момент мені не зрозуміло навіщо це робити: браузери, пошукові системи і парсери справляються граючи з таким текстом, а ганяти cpu просто так і робити код нечитабельним мені зовсім не хочеться. Буду радий конкретного прикладу.
  • Ймовірно,
    ru_typus
    впорається з українськими та білоруськими текстами (а можливо, і з іншими), якщо так, я внесу це опис проекту.
Ніби все.
P. S. якесь пекло з підсвічуванням інлайн-коду на хабре.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.