Metadata-Version: 2.4
Name: uniconv
Version: 2.0.0
Summary: Universal unit converter for engineers
Author-email: Mihanchos <shofer2007@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/SKB-CADDep/uniconv
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.7
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# UniConv: конвертер инженерных единиц

Библиотека конвертации единиц с внешним реестром 48 инженерных величин.
Требуется Python ≥3.7; зависимости времени выполнения отсутствуют.

Установка версии 2.0.0 из PyPI:

```bash
python -m pip install "uniconv==2.0.0"
```

Для установки из клонированного репозитория выполните:

```bash
python -m pip install .
```

## API по ID

Все методы принимают точный строковый ID из реестра: `"0"` — давление,
`"1"` — температура, `"47"` — угловая скорость. Имена величин и UI-метки
не используются для поиска. Это несовместимое изменение относительно API 1.0.1:
`parameter_type`, `from_unit`, `to_unit` заменены на `type_id`, `from_u`, `to_u`.

```python
from uniconv import UnitConverter

uc = UnitConverter()
pressure = uc.convert(10, "бар", "кгс/см2", "0")
# Именованные аргументы также поддерживаются:
temperature = uc.convert(212, from_u="F", to_u="C", type_id="1")  # 100 °C
reaumur = uc.convert(100, "C", "Re", "1")  # 80 °Re

print(uc.get_parameter_info("0"))
# {'id': '0', 'name_RU': 'Давление', 'name_ENG': 'Pressure', 'base_unit': 'кгс/см2'}
print(uc.get_available_units("0")[0])
# {'code': 'кгс/см2', 'ui': 'кгс/см²'}

base_value = uc.to_base(10, "бар", "0")
value = uc.from_base(base_value, "МПа", "0")
base_code = uc.get_base_unit("0")
```

`get_available_units()` возвращает список словарей `code`/`ui` в порядке реестра.
`get_parameter_info()` возвращает независимый словарь метаданных.
Преобразования используют коды из `factors`, например `кгс/см2`, а не UI-метку `кгс/см²`.
Линейная формула: `value * factor_from / factor_to`. Коэффициенты, зависящие
от стандартных физических величин, выводятся из именованных констант без округления.
Они могут отличаться от округлённых чисел в приложении спецификации: например,
радианы вычисляются через `math.pi`, а фунт — через точное значение `LB_TO_KG`.
Остальные справочные коэффициенты сохраняют точность исходного реестра.
Температура преобразуется через Celsius; доступны C, K, F, Re. Отрицательные
значения поддерживаются; проверка физической допустимости значений не выполняется.

## Ошибки

- `UnknownParameterError`: неизвестный строковый ID (включая имя вместо ID или целочисленный ID).
- `UnknownUnitError`: неизвестный код исходной или целевой единицы.
- `DataLoadError`: отсутствующий, повреждённый или структурно неверный JSON-ресурс.
  Сообщение содержит имя ресурса и причину; исходное исключение доступно через `__cause__`.

Исключения экспортируются из `uniconv`. Проверка ID и обоих кодов выполняется
также при преобразовании единицы в себя; для существующей единицы исходное значение
возвращается без промежуточного пересчёта.

## Расширение экземпляра

```python
uc.add_parameter("48", parameter_name="Пользовательская скорость",
                 parameter_name_eng="Custom velocity",
                 base_unit_symbol="m/s", base_unit_name="Metre per second")
uc.add_unit("48", unit_symbol="km/h", unit_name="Kilometre per hour",
            to_base=1 / 3.6, display_label="км/ч")
assert abs(uc.convert(36, "km/h", "m/s", "48") - 10) < 1e-10
```

Новый ID должен быть десятичной строкой и отсутствовать в экземпляре.
Числовой `to_base` — множитель в направлении базовой единицы; обратный множитель
вычисляется автоматически. Явный числовой `from_base` тоже является множителем.
Для функции `to_base` нужно явно передать обратную функцию `from_base`.
Базовую единицу нельзя переопределять. Изменения не затрагивают другие экземпляры
и не записываются в JSON. `unit_name` и `base_unit_name` сохранены как аргументы
методов расширения; UI-метка задаётся через `display_label`, по умолчанию равна коду.

## Твёрдость

Для ID `"34"` доступны шкалы d10, HB, HRA, HRC, HRB, HV, HSD.
Конвертация выполняется через HB по таблице из 441 строки.

```python
assert uc.convert(712, "HB", "HV", "34") == 1016
assert uc.convert(100, "HRB", "HB", "34") == 244
assert uc.convert(709, "HB", "HV", "34") == 1007.5  # Интерполяция
assert uc.convert(1007.5, "HV", "HB", "34") == 709
assert uc.convert(713, "HB", "HV", "34") is None  # Вне диапазона
assert uc.convert(712, "HB", "HRB", "34") is None  # Нет данных
```

Пропуски не участвуют в расчёте и разрывают интервал: интерполяция через строки
с `null` и экстраполяция запрещены. Если исходное значение повторяется в таблице,
используется первая подходящая строка; из-за округления табличных значений точная
обратимость для твёрдости не гарантируется. Конвертация шкалы в себя сохраняет
исходное значение после проверки кода, включая значения вне таблицы.

## Пресеты

Пресеты определяют единицы отображения, не изменяя хранимые значения или реестр.

```python
assert uc.list_presets() == ["SI", "TECH", "IMPERIAL"]
raw = uc.get_preset("SI")              # Исходный словарь ID -> код
assert raw["0"] == "МПа"
resolved = uc.apply_preset("SI")       # Проверенные пары с UI-метками
assert resolved["0"] == {"code": "МПа", "ui": "МПа"}
assert uc.get_preset("unknown") is None
assert uc.apply_preset("unknown") is None

stored_pressure = 1  # В базовой единице кгс/см2
unit = resolved["0"]
ui_pressure = uc.convert(stored_pressure, uc.get_base_unit("0"), unit["code"], "0")
print(ui_pressure, unit["ui"])
```

`get_preset()` возвращает копию исходного словаря, включая невалидные пары.
`apply_preset()` пропускает неизвестные ID и коды, записывая предупреждение через
стандартный `logging` в логгер `uniconv.converter`. UI-метки берутся из реестра.
В исходных данных SI содержит 2 невалидные пары, TECH — 1, IMPERIAL — 10;
при их применении предупреждения ожидаемы. Отсутствующие в пресете ID допустимы.

## Константы и внешние данные

```python
from uniconv import constants

assert constants.KGF_TO_N == constants.G_STANDARD
assert constants.LBF_TO_N == constants.LB_TO_KG * constants.G_STANDARD
```

В JSON коэффициент может ссылаться на константу (`"@G_STANDARD"`) или содержать
арифметическое выражение (`"@LBF_TO_N / (@INCH_TO_MM / 1000)**2 / 1e6"`).
Загрузчик разрешает числовые литералы, имена констант, скобки и операции
`+`, `-`, `*`, `/`, `**`; вызовы функций и доступ к атрибутам запрещены.
Ссылки раскрываются один раз при создании экземпляра. Затем конвертация
использует готовые числовые коэффициенты, без `eval` и повторного разбора JSON.
Неизвестная константа или неверное выражение вызывает `DataLoadError` с ID и кодом.

В пакет входят `units_registry.json`, `hardness_data.json`, `presets.json`.
Они загружаются независимо от рабочего каталога. Табличные колонки идут в порядке
[d10, HB, HRA, HRC, HRB, HV, HSD]; пропуски записаны как JSON `null`.
Загруженные данные доступны через `uc.parameters`, `uc.hardness_data`, `uc.presets`.
Таблица интерполяции подготовлена при создании экземпляра; изменение
`hardness_data` после инициализации не перестраивает её.

Реализованы DEV-01—DEV-09. Старые имена параметров и ключевые аргументы
`parameter_type`, `from_unit`, `to_unit` не поддерживаются. Вспомогательные методы
и динамическое расширение сохранены с ID. Публичные экспорты: `UnitConverter`,
`UnknownParameterError`, `UnknownUnitError`, `DataLoadError`, `constants`.

## Проверка

```bash
python -m unittest discover -s tests -v
python -m build
```

Полная спецификация находится в [docs/uniconv.md](docs/uniconv.md).

## Лицензия

MIT — см. [LICENSE](LICENSE).
