Allowing attachment points to be pulled from descriptions on sync
This commit is contained in:
1 parent
e24b8e5ea6
commit
b2d01f1ab0
1 file changed
+32
-12
@@ -55,7 +55,7 @@ MM_PER_INCH = 25.4
|
|||||||
# M50x.75 - No leading digit on floats
|
# M50x.75 - No leading digit on floats
|
||||||
# Float pattern: \d*\.?\d+
|
# Float pattern: \d*\.?\d+
|
||||||
_ISO_THREAD_RE = re.compile(
|
_ISO_THREAD_RE = re.compile(
|
||||||
r"^M\s*(?P<diameter>\d*\.?\d+)\s*[xX-]\s*P?(?P<pitch>\d*\.?\d+)(?P<extra>.*)$"
|
r"M\s*(?P<diameter>\d*\.?\d+)\s*[xX-]\s*P?(?P<pitch>\d*\.?\d+)(?P<extra>.*)"
|
||||||
)
|
)
|
||||||
|
|
||||||
# e.g.
|
# e.g.
|
||||||
@@ -65,8 +65,8 @@ _ISO_THREAD_RE = re.compile(
|
|||||||
#
|
#
|
||||||
# Leading digit / period, one or more digits, a dash, then
|
# Leading digit / period, one or more digits, a dash, then
|
||||||
_UNC_THREAD_RE = re.compile(
|
_UNC_THREAD_RE = re.compile(
|
||||||
r"^(?P<diameter>\d*\.?\d+)\s*-\s*(?P<tpi>\d*\.?\d+)"
|
r"(?P<diameter>\d*\.?\d+)\s*-\s*(?P<tpi>\d*\.?\d+)"
|
||||||
r"\s*(?P<series>UNEF|UNC|UNF|UNS|UN)?$",
|
r"\s*(?P<series>UNEF|UNC|UNF|UNS|UN)?",
|
||||||
re.IGNORECASE,
|
re.IGNORECASE,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -111,7 +111,9 @@ async def _get_or_create_attachment_point_name(db: AsyncSession, name: str):
|
|||||||
return apn
|
return apn
|
||||||
|
|
||||||
|
|
||||||
async def _add_attachment_point(db: AsyncSession, ap: AugmentedPart, ip: ImportedPart) -> None:
|
async def _add_attachment_point(
|
||||||
|
db: AsyncSession, ap: AugmentedPart, ip: ImportedPart
|
||||||
|
) -> None:
|
||||||
"""Infer and create an attachment point for a newly-synced AugmentedPart.
|
"""Infer and create an attachment point for a newly-synced AugmentedPart.
|
||||||
|
|
||||||
Preference order: TBXThreadAttribute (ISO/UNC thread) then ProductODmm/in
|
Preference order: TBXThreadAttribute (ISO/UNC thread) then ProductODmm/in
|
||||||
@@ -119,7 +121,11 @@ async def _add_attachment_point(db: AsyncSession, ap: AugmentedPart, ip: Importe
|
|||||||
attribute is present but unparseable.
|
attribute is present but unparseable.
|
||||||
"""
|
"""
|
||||||
thread_value = (ip.TBXThreadAttribute or "").strip()
|
thread_value = (ip.TBXThreadAttribute or "").strip()
|
||||||
parsed = _parse_thread_attribute(thread_value) if thread_value else None
|
parsed = None
|
||||||
|
if thread_value:
|
||||||
|
parsed = _parse_thread_attribute(thread_value)
|
||||||
|
else:
|
||||||
|
parsed = _parse_thread_attribute(ip.Description or "")
|
||||||
|
|
||||||
if parsed is not None:
|
if parsed is not None:
|
||||||
kind, fields = parsed
|
kind, fields = parsed
|
||||||
@@ -127,7 +133,9 @@ async def _add_attachment_point(db: AsyncSession, ap: AugmentedPart, ip: Importe
|
|||||||
|
|
||||||
if kind == "iso":
|
if kind == "iso":
|
||||||
depth_mm = _parse_float(ip.ProductMaxThreadDepthmm)
|
depth_mm = _parse_float(ip.ProductMaxThreadDepthmm)
|
||||||
thread = await iso_thread_crud.get_by_values(db, depth_mm=depth_mm, **fields)
|
thread = await iso_thread_crud.get_by_values(
|
||||||
|
db, depth_mm=depth_mm, **fields
|
||||||
|
)
|
||||||
if thread is None:
|
if thread is None:
|
||||||
thread = await iso_thread_crud.create(db, depth_mm=depth_mm, **fields)
|
thread = await iso_thread_crud.create(db, depth_mm=depth_mm, **fields)
|
||||||
await attachment_point_crud.create(
|
await attachment_point_crud.create(
|
||||||
@@ -138,7 +146,9 @@ async def _add_attachment_point(db: AsyncSession, ap: AugmentedPart, ip: Importe
|
|||||||
)
|
)
|
||||||
elif kind == "unc":
|
elif kind == "unc":
|
||||||
depth_in = _parse_float(ip.ProductMaxThreadDepthin)
|
depth_in = _parse_float(ip.ProductMaxThreadDepthin)
|
||||||
thread = await unc_thread_crud.get_by_values(db, depth_in=depth_in, **fields)
|
thread = await unc_thread_crud.get_by_values(
|
||||||
|
db, depth_in=depth_in, **fields
|
||||||
|
)
|
||||||
if thread is None:
|
if thread is None:
|
||||||
thread = await unc_thread_crud.create(db, depth_in=depth_in, **fields)
|
thread = await unc_thread_crud.create(db, depth_in=depth_in, **fields)
|
||||||
await attachment_point_crud.create(
|
await attachment_point_crud.create(
|
||||||
@@ -236,7 +246,9 @@ async def sync(db: AsyncSession) -> AugmentedPartSyncResult:
|
|||||||
# ------------------------------------------------------------------ phase 1
|
# ------------------------------------------------------------------ phase 1
|
||||||
|
|
||||||
# IDs referenced in existing associations
|
# IDs referenced in existing associations
|
||||||
result = await db.execute(select(augmented_part_imported_parts.c.imported_part_id).distinct())
|
result = await db.execute(
|
||||||
|
select(augmented_part_imported_parts.c.imported_part_id).distinct()
|
||||||
|
)
|
||||||
all_linked_ids: set[str] = {row[0] for row in result.all()}
|
all_linked_ids: set[str] = {row[0] for row in result.all()}
|
||||||
|
|
||||||
# IDs that still exist in imported_parts
|
# IDs that still exist in imported_parts
|
||||||
@@ -250,7 +262,9 @@ async def sync(db: AsyncSession) -> AugmentedPartSyncResult:
|
|||||||
# Which AugmentedParts are affected?
|
# Which AugmentedParts are affected?
|
||||||
result = await db.execute(
|
result = await db.execute(
|
||||||
select(augmented_part_imported_parts.c.augmented_part_id).where(
|
select(augmented_part_imported_parts.c.augmented_part_id).where(
|
||||||
augmented_part_imported_parts.c.imported_part_id.in_(orphaned_import_ids)
|
augmented_part_imported_parts.c.imported_part_id.in_(
|
||||||
|
orphaned_import_ids
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
orphaned_ap_ids: set[int] = {row[0] for row in result.all()}
|
orphaned_ap_ids: set[int] = {row[0] for row in result.all()}
|
||||||
@@ -258,7 +272,9 @@ async def sync(db: AsyncSession) -> AugmentedPartSyncResult:
|
|||||||
# Remove the stale association rows
|
# Remove the stale association rows
|
||||||
await db.execute(
|
await db.execute(
|
||||||
augmented_part_imported_parts.delete().where(
|
augmented_part_imported_parts.delete().where(
|
||||||
augmented_part_imported_parts.c.imported_part_id.in_(orphaned_import_ids)
|
augmented_part_imported_parts.c.imported_part_id.in_(
|
||||||
|
orphaned_import_ids
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
await db.flush()
|
await db.flush()
|
||||||
@@ -281,7 +297,9 @@ async def sync(db: AsyncSession) -> AugmentedPartSyncResult:
|
|||||||
# ------------------------------------------------------------------ phase 2
|
# ------------------------------------------------------------------ phase 2
|
||||||
|
|
||||||
# Re-query linked IDs after phase 1 cleanup
|
# Re-query linked IDs after phase 1 cleanup
|
||||||
result = await db.execute(select(augmented_part_imported_parts.c.imported_part_id).distinct())
|
result = await db.execute(
|
||||||
|
select(augmented_part_imported_parts.c.imported_part_id).distinct()
|
||||||
|
)
|
||||||
now_linked_ids: set[str] = {row[0] for row in result.all()}
|
now_linked_ids: set[str] = {row[0] for row in result.all()}
|
||||||
unlinked_ids = current_ids - now_linked_ids
|
unlinked_ids = current_ids - now_linked_ids
|
||||||
|
|
||||||
@@ -289,7 +307,9 @@ async def sync(db: AsyncSession) -> AugmentedPartSyncResult:
|
|||||||
skipped = 0
|
skipped = 0
|
||||||
|
|
||||||
if not unlinked_ids:
|
if not unlinked_ids:
|
||||||
return AugmentedPartSyncResult(created=created, deleted=deleted, skipped=skipped)
|
return AugmentedPartSyncResult(
|
||||||
|
created=created, deleted=deleted, skipped=skipped
|
||||||
|
)
|
||||||
|
|
||||||
result = await db.execute(
|
result = await db.execute(
|
||||||
select(ImportedPart).where(ImportedPart.InventoryID.in_(unlinked_ids))
|
select(ImportedPart).where(ImportedPart.InventoryID.in_(unlinked_ids))
|
||||||
|
|||||||
Reference in new issue
Block a user