Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 2 additions & 60 deletions common.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,9 @@
import csv
import re
from datetime import datetime
from os import makedirs, path
from os import path

from typing import Any, Dict, Iterable, List, OrderedDict, Union

# String escape sequences
STRING_ESCAPE_SEQUENCES = (
('\\', '\\\\'), # Must be the first one to avoid recursion!
('\b', '\\b'),
('\f', '\\f'),
('\n', '\\n'),
('\r', '\\r'),
('\t', '\\t'),
('\v', '\\v'),
('"', '\\"'),
)
from typing import Any, Dict, List, OrderedDict, Union


def init_cache(uuid_cache_file: str) -> Dict[str, str]:
Expand Down Expand Up @@ -52,29 +40,6 @@ def now() -> str:
return datetime.utcnow().replace(microsecond=0).isoformat() + 'Z'


def escape_string(string: str) -> str:
"""
Escape a string according to LibrePCB S-Expression escaping rules.
"""
for search, replacement in STRING_ESCAPE_SEQUENCES:
string = string.replace(search, replacement)
return string


def format_float(number: float) -> str:
"""
Format a float according to LibrePCB normalization rules.
"""
formatted = '{:.3f}'.format(number)
if formatted == '-0.000':
return '0.0' # Remove useless sign
if formatted[-1] == '0':
if formatted[-2] == '0':
return formatted[:-2]
return formatted[:-1]
return formatted


def format_ipc_dimension(number: float, decimal_places: int = 2) -> str:
"""
Format a dimension (e.g. lead span or height) according to IPC rules.
Expand All @@ -91,13 +56,6 @@ def format_ipc_dimension(number: float, decimal_places: int = 2) -> str:
return str(int(round(number, 6 - decimal_places)))


def indent(level: int, lines: Iterable[str]) -> List[str]:
"""
Indent the lines by the specified level.
"""
return [' ' * level + line for line in lines]


def sign(val: Union[int, float]) -> int:
"""
Return 1 for positive or zero values, -1 otherwise.
Expand Down Expand Up @@ -135,19 +93,3 @@ def _convert(text: str) -> Union[int, str]:
return int(text) if text.isdigit() else text

return [_convert(x) for x in re.split(r'(\d+)', key) if x]


def serialize_common(
serializable: Any, output_directory: str, uuid: str, long_type: str, short_type: str
) -> None:
"""
Centralized serialize() implementation shared between Component, Symbol, Device, Package
"""
dir_path = path.join(output_directory, uuid)
if not (path.exists(dir_path) and path.isdir(dir_path)):
makedirs(dir_path)
with open(path.join(dir_path, f'.librepcb-{short_type}'), 'w', newline='\n') as f:
f.write('2\n')
with open(path.join(dir_path, f'{long_type}.lp'), 'w', newline='\n') as f:
f.write(str(serializable))
f.write('\n')
4 changes: 1 addition & 3 deletions entities/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@

from typing import List, Optional

from common import escape_string, format_float

from .helper import indent_entities
from .helper import escape_string, format_float, indent_entities


class EnumValue(Enum):
Expand Down
4 changes: 1 addition & 3 deletions entities/component.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from typing import Iterable, List, Optional

from common import serialize_common

from .common import (
Author,
BoolValue,
Expand All @@ -19,7 +17,7 @@
UUIDValue,
Version,
)
from .helper import indent_entities
from .helper import indent_entities, serialize_common


class DefaultValue(StringValue):
Expand Down
8 changes: 3 additions & 5 deletions entities/device.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
from typing import Iterable, List, Optional

from common import escape_string, serialize_common
from entities.attribute import Attribute
from entities.common import BoolValue

from .attribute import Attribute
from .common import (
Author,
BoolValue,
Category,
Created,
Deprecated,
Expand All @@ -19,7 +17,7 @@
Version,
)
from .component import SignalUUID
from .helper import indent_entities
from .helper import escape_string, indent_entities, serialize_common


class ComponentUUID(UUIDValue):
Expand Down
62 changes: 60 additions & 2 deletions entities/helper.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
from typing import Any, Iterable
from os import makedirs, path

from common import indent
from typing import Any, Iterable, List

# String escape sequences
STRING_ESCAPE_SEQUENCES = (
('\\', '\\\\'), # Must be the first one to avoid recursion!
('\b', '\\b'),
('\f', '\\f'),
('\n', '\\n'),
('\r', '\\r'),
('\t', '\\t'),
('\v', '\\v'),
('"', '\\"'),
)


def indent(level: int, lines: Iterable[str]) -> List[str]:
"""
Indent the lines by the specified level.
"""
return [' ' * level + line for line in lines]


def indent_entity(entity: Any) -> str:
Expand All @@ -27,3 +46,42 @@ def indent_entities(entities: Iterable[Any]) -> str:
' (bar "2")\\n (bar "3")\\n'
"""
return ''.join(map(indent_entity, entities))


def escape_string(string: str) -> str:
"""
Escape a string according to LibrePCB S-Expression escaping rules.
"""
for search, replacement in STRING_ESCAPE_SEQUENCES:
string = string.replace(search, replacement)
return string


def format_float(number: float) -> str:
"""
Format a float according to LibrePCB normalization rules.
"""
formatted = '{:.3f}'.format(number)
if formatted == '-0.000':
return '0.0' # Remove useless sign
if formatted[-1] == '0':
if formatted[-2] == '0':
return formatted[:-2]
return formatted[:-1]
return formatted


def serialize_common(
serializable: Any, output_directory: str, uuid: str, long_type: str, short_type: str
) -> None:
"""
Centralized serialize() implementation shared between Component, Symbol, Device, Package
"""
dir_path = path.join(output_directory, uuid)
if not (path.exists(dir_path) and path.isdir(dir_path)):
makedirs(dir_path)
with open(path.join(dir_path, f'.librepcb-{short_type}'), 'w', newline='\n') as f:
f.write('2\n')
with open(path.join(dir_path, f'{long_type}.lp'), 'w', newline='\n') as f:
f.write(str(serializable))
f.write('\n')
4 changes: 1 addition & 3 deletions entities/package.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from typing import Iterable, List, Optional, Union

from common import format_float, serialize_common

from .common import (
Align,
Author,
Expand Down Expand Up @@ -29,7 +27,7 @@
Version,
Vertex,
)
from .helper import indent_entities
from .helper import format_float, indent_entities, serialize_common


class Package3DModel:
Expand Down
4 changes: 1 addition & 3 deletions entities/symbol.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from typing import Iterable, List

from common import format_float, serialize_common

from .common import (
Author,
Category,
Expand All @@ -20,7 +18,7 @@
Text,
Version,
)
from .helper import indent_entities
from .helper import format_float, indent_entities, serialize_common


class NamePosition:
Expand Down
3 changes: 2 additions & 1 deletion test_common.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pytest

from common import escape_string, format_float, format_ipc_dimension, human_sort_key, sign
from common import format_ipc_dimension, human_sort_key, sign
from entities.helper import escape_string, format_float


@pytest.mark.parametrize(
Expand Down
Loading