-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
429 additions
and
398 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import pytest | ||
|
||
from webpub.common import slugify, urlpath_join | ||
|
||
|
||
@pytest.mark.parametrize('input_str,expected_str', [ | ||
('Бухгалтерия 2345', 'buhgalterija-2345'), | ||
('true & false', 'true-false'), | ||
]) | ||
def test_slugify(input_str: str, expected_str: str): | ||
assert slugify(input_str) == expected_str | ||
|
||
|
||
@pytest.mark.parametrize('prefix,url_path,expected_str', [ | ||
('/base', 'path', '/base/path'), | ||
('/base', '/path', '/base/path'), | ||
('/base/', 'path', '/base/path'), | ||
('/base/', '/path', '/base/path'), | ||
('/base/', '/base/path', '/base/path'), | ||
]) | ||
def test_urlpath_join(prefix: str, url_path: str, expected_str: str): | ||
assert urlpath_join(prefix, url_path) == expected_str |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
import os | ||
import re | ||
from typing import Optional, Iterator, List | ||
|
||
import jinja2 | ||
|
||
from .common import VRDConfig, default_templates_env, files_encoding, urlpath_join | ||
from .webpublication import WebPublication | ||
|
||
|
||
class ApacheConfig: | ||
""" apache config """ | ||
|
||
start_tag: str = '# --- WEBPUB1C PUBLICATION START:' | ||
end_tag: str = '# --- WEBPUB1C PUBLICATION END:' | ||
|
||
def __init__(self, filename: str, | ||
vrd_path: str, | ||
dir_path: str, | ||
url_base: str, | ||
vrd_params: Optional[VRDConfig] = None, | ||
templates_env: Optional[jinja2.Environment] = None): | ||
self.filename: str = filename | ||
self.vrd_path: str = vrd_path | ||
self.dir_path: str = dir_path | ||
self.url_base: str = url_base | ||
self.vrd_params: Optional[VRDConfig] = vrd_params | ||
|
||
if templates_env is None: | ||
self.templates_env = default_templates_env | ||
else: | ||
self.templates_env = templates_env | ||
|
||
def is_valid(self) -> bool: | ||
return os.path.isfile(self.filename) | ||
|
||
def _check(self): | ||
if not self.is_valid(): | ||
raise ValueError('invalid apache config') | ||
|
||
@property | ||
def text(self) -> str: | ||
self._check() | ||
|
||
with open(self.filename, 'r', encoding=files_encoding) as f: | ||
txt: str = f.read() | ||
return txt | ||
|
||
def has_1cws_module(self) -> bool: | ||
ws_expr = re.compile(r'^LoadModule\s_1cws_module\s.*$', re.M) | ||
result: bool = (ws_expr.search(self.text) is not None) | ||
|
||
return result | ||
|
||
def add_1cws_module(self, module_filename: str): | ||
if self.has_1cws_module(): | ||
return | ||
|
||
with open(self.filename, "a", encoding=files_encoding) as f: | ||
f.write(f'\nLoadModule _1cws_module "{module_filename}"\n') | ||
|
||
@property | ||
def publications(self) -> Iterator[str]: | ||
start_expr = re.compile(r'^{}\s(.+)$'.format(re.escape(ApacheConfig.start_tag)), re.M) | ||
for match in start_expr.finditer(self.text): | ||
yield match.group(1).strip() | ||
|
||
def iter(self) -> Iterator[WebPublication]: | ||
start_pub = re.compile(r'^{}\s'.format(re.escape(ApacheConfig.start_tag))) | ||
start_name = re.compile(r'^{}\s(.+)$'.format(re.escape(ApacheConfig.start_tag))) | ||
end_pub = re.compile(r'^{}\s'.format(re.escape(ApacheConfig.end_tag))) | ||
|
||
is_pub_started: bool = False | ||
cur_pub_name: str = "" | ||
cur_pub_lines: List[str] = [] | ||
lines: List[str] = self.text.splitlines(keepends=True) | ||
for line in lines: | ||
if is_pub_started: | ||
if end_pub.match(line): | ||
if 0 == len(cur_pub_lines): | ||
raise ValueError('can\'t parse config :(') | ||
publication = WebPublication.from_config(cur_pub_name, ''.join(cur_pub_lines), | ||
templates_env=self.templates_env) | ||
yield publication | ||
cur_pub_name = "" | ||
cur_pub_lines.clear() | ||
is_pub_started = False | ||
else: | ||
cur_pub_lines.append(line) | ||
continue | ||
if start_pub.match(line): | ||
is_pub_started = True | ||
match = start_name.match(line) | ||
if match is None: | ||
raise ValueError('can\'t parse config :(') | ||
cur_pub_name = match.group(1).strip() | ||
|
||
def is_publicated(self, ibname: str) -> bool: | ||
return ibname in self.publications | ||
|
||
def create_publication(self, ibname: str, url_path: Optional[str] = None, infobase_filepath='') -> WebPublication: | ||
if self.is_publicated(ibname): | ||
raise KeyError(f'infobase "{ibname}" already publicated') | ||
|
||
publication = WebPublication(ibname, vrd_params=self.vrd_params, templates_env=self.templates_env, | ||
infobase_filepath=infobase_filepath) | ||
publication.generate_paths(self.dir_path, self.vrd_path, self.url_base) | ||
|
||
if url_path is not None: | ||
publication.url_path = urlpath_join(self.url_base, url_path) | ||
|
||
if not publication.is_ok_to_create(): | ||
raise ValueError(f'can\'t create publication: {publication.describe()}') | ||
|
||
publication.create() | ||
return publication | ||
|
||
def add_publication(self, publication: WebPublication) -> None: | ||
if self.is_publicated(publication.name): | ||
raise KeyError(f'infobase "{publication.name}" already publicated') | ||
|
||
pub_cfg = publication.to_config() | ||
with open(self.filename, "a", encoding=files_encoding) as f: | ||
f.write(f'\n{ApacheConfig.start_tag} {publication.name}\n') | ||
f.write(pub_cfg) | ||
f.write(f'\n{ApacheConfig.end_tag} {publication.name}') | ||
|
||
def get_publication(self, ibname: str) -> Optional[WebPublication]: | ||
if not self.is_publicated(ibname): | ||
return None | ||
|
||
start_pub = re.compile(r'^{}\s{}'.format(re.escape(ApacheConfig.start_tag), re.escape(ibname))) | ||
end_pub = re.compile(r'^{}\s{}'.format(re.escape(ApacheConfig.end_tag), re.escape(ibname))) | ||
|
||
is_pub_started: bool = False | ||
pub_lines: List[str] = [] | ||
lines: List[str] = self.text.splitlines(keepends=True) | ||
for line in lines: | ||
if is_pub_started: | ||
if end_pub.match(line): | ||
break | ||
else: | ||
pub_lines.append(line) | ||
continue | ||
if start_pub.match(line): | ||
is_pub_started = True | ||
|
||
if 0 == len(pub_lines): | ||
raise ValueError('can\'t parse config :(') | ||
|
||
publication = WebPublication.from_config(ibname, ''.join(pub_lines), templates_env=self.templates_env) | ||
return publication | ||
|
||
def remove_publication(self, ibname: str, destroy: bool = True): | ||
if not self.is_publicated(ibname): | ||
raise KeyError(f'infobase "{ibname}" not publicated') | ||
|
||
start_pub = re.compile(r'^{}\s{}'.format(re.escape(ApacheConfig.start_tag), re.escape(ibname))) | ||
end_pub = re.compile(r'^{}\s{}'.format(re.escape(ApacheConfig.end_tag), re.escape(ibname))) | ||
is_pub_started: bool = False | ||
|
||
# filter lines for new config and publication | ||
pub_lines: List[str] = [] | ||
new_lines: List[str] = [] | ||
lines: List[str] = self.text.splitlines(keepends=True) | ||
for line in lines: | ||
if is_pub_started: | ||
if end_pub.match(line): | ||
is_pub_started = False | ||
# remove last empty line | ||
if len(new_lines) > 0: | ||
if new_lines[-1].strip() == '': | ||
new_lines.pop() | ||
else: | ||
pub_lines.append(line) | ||
continue | ||
if start_pub.match(line): | ||
is_pub_started = True | ||
continue | ||
new_lines.append(line) | ||
|
||
# remove vrd and directory | ||
if destroy: | ||
publication = WebPublication.from_config(ibname, ''.join(pub_lines)) | ||
publication.remove() | ||
|
||
# write new config | ||
with open(self.filename, "w", encoding=files_encoding) as f: | ||
f.write(''.join(new_lines)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import os | ||
import re | ||
import unicodedata | ||
from typing import Dict, Union | ||
|
||
import jinja2 | ||
from transliterate import translit | ||
|
||
VRDConfig = Dict[str, Union[str, None]] | ||
DictConfig = Dict[str, Union[str, 'DictConfig', None]] | ||
|
||
files_encoding: str = 'utf-8' | ||
default_templates_dir = os.path.join(os.path.dirname(__file__), '../templates') | ||
default_templates_env = jinja2.Environment(loader=jinja2.FileSystemLoader(default_templates_dir)) | ||
|
||
|
||
def slugify(value: str, lang: str = 'ru') -> str: | ||
if value != unicodedata.normalize('NFKD', value).encode('ascii', 'ignore').decode('ascii'): | ||
value = translit(value, lang, reversed=True) | ||
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore').decode('ascii') | ||
value = re.sub(r'[^\w\s-]', '', value.lower()) | ||
return re.sub(r'[-\s]+', '-', value).strip('-_') | ||
|
||
|
||
def urlpath_join(prefix: str, url_path: str) -> str: | ||
if not prefix.endswith('/'): | ||
prefix += '/' | ||
if not url_path.startswith(prefix): | ||
if url_path.startswith('/'): | ||
url_path = url_path.lstrip('/') | ||
url_path = prefix + url_path | ||
return url_path |
Oops, something went wrong.