partsdb

electronic parts inventory
git clone https://git.e1e0.net/partsdb.git
Log | Files | Refs | README | LICENSE

helpers.py (6660B)


      1 #!/usr/bin/env python3
      2 # -*- coding: utf-8 -*-
      3 # vim:fenc=utf-8
      4 
      5 import datetime
      6 import json
      7 import subprocess
      8 import tempfile
      9 import time
     10 import shutil
     11 
     12 from os import listdir
     13 
     14 from partsdb import exports
     15 
     16 
     17 def print_parts_list(parts, output="full"):
     18     if output == "short":
     19         _list_ascii_short(parts)
     20     if output == "full":
     21         _list_ascii(parts)
     22     if output == "json":
     23         _list_json(parts)
     24 
     25 
     26 def _list_ascii(parts):
     27     # max takes an iterable and key is a function where iterables are
     28     # passed and comparison performed, so we look at the longest desc to
     29     # get the lenght of the field.  We also check if the header is longer,
     30     # the result is whatever is longer
     31     l_mpn = len(max(parts, key=lambda k: len(k["mpn"]))["mpn"])
     32     l_cat = len(max(parts, key=lambda k: len(k["cname"]))["cname"])
     33     l_man = len(max(parts, key=lambda k: len(k["manufacturer"]))["manufacturer"])
     34     l_desc = len(max(parts, key=lambda k: len(k["description"]))["description"])
     35     l_cat = l_cat if l_cat > len("Category") else len("Category")
     36     l_man = l_man if l_man > len("Manufacturer") else len("Manufacturer")
     37     l_desc = l_desc if l_desc > len("Description") else len("Description")
     38 
     39     header = (
     40         f"| {'ID':5} | {'PN':4} | "
     41         f"{'MPN':{l_mpn}} | "
     42         f"{'Category':{l_cat}} | "
     43         f"{'Manufacturer':{l_man}} | "
     44         f"{'Description':{l_desc}} | "
     45         f"{'Type':4} | "
     46         f"{'Footp':6} | "
     47         f"{'Qty':4} |"
     48     )
     49     for i, p in enumerate(parts):
     50         if i % 25 == 0:
     51             print("-" * len(header))
     52             print(header)
     53             print("-" * len(header))
     54         print(
     55             f"| {p['id']:<5} | {p['id']:04X} | "
     56             f"{p['mpn']:{l_mpn}} | "
     57             f"{p['cname']:{l_cat}} | "
     58             f"{_sanitize_value(p['manufacturer']):{l_man}} | "
     59             f"{_sanitize_value(p['description']):{l_desc}} | "
     60             f"{_sanitize_value(p['part_type'])[0:3]:4} | "
     61             f"{_sanitize_value(p['footprint'])[0:5]:6} | "
     62             f"{p['quantity']:4} |"
     63         )
     64 
     65 
     66 def _list_ascii_short(parts):
     67     header = (
     68         f"| {'ID':4} | "
     69         f"{'Category':8} | "
     70         f"{'MPN':10} | "
     71         f"{'Manufacturer':16} | "
     72         f"{'Description':25} |"
     73     )
     74     for i, p in enumerate(parts):
     75         if i % 25 == 0:
     76             print("-" * 79)
     77             print(header)
     78             print("-" * 79)
     79         print(
     80             f"| {p['id']:<4} | "
     81             f"{p['cname'][0:7]:8} | "
     82             f"{_sanitize_value(p['mpn'])[0:9]:10} | "
     83             f"{_sanitize_value(p['manufacturer'])[0:15]:16} | "
     84             f"{_sanitize_value(p['description'])[0:24]:25} |"
     85         )
     86 
     87 
     88 def _list_json(parts):
     89     p = [dict(zip(part.keys(), part)) for part in parts]
     90     print(json.dumps({"parts": p}))
     91 
     92 
     93 def print_part(p, history, output="full"):
     94     if output == "full":
     95         _part_ascii(p, history)
     96     if output == "json":
     97         _part_json(p, history)
     98 
     99 
    100 def _part_ascii(p, history):
    101     print(f"PN: {p['id']:04X}\tMPN: {p['mpn']}\tManufacturer: {p['manufacturer']}")
    102     print(
    103         f"Category: {p['cat']}\tType: {p['part_type']}" f"\tFootprint: {p['footprint']}"
    104     )
    105     print(f"Storage: {p['storage']}")
    106     print(f"Created: {p['insert_date']}" f"\tUpdated: {p['update_date']}\n")
    107     print(f"Description:\n{p['description']}\n")
    108     print(f"Specs:\n{p['specs']}")
    109 
    110     if p["datasheet"] is not None:
    111         print("This part has a datasheet available.")
    112     if p["image"] is not None:
    113         print("This part has an image available.")
    114 
    115     print(f"\nQuantity: {p['quantity']}")
    116     # here should go the historical data.
    117     if history:
    118         print("History:")
    119         for h in history:
    120             print(f"{h['insert_date']} | " f"{h['movement']:4} | " f"{h['mcomment']}")
    121 
    122 
    123 def _part_json(part, history):
    124     part = dict(zip(part.keys(), part))
    125     # remove bytes data if present.  For now is useless in this output.
    126     del part["datasheet"]
    127     del part["image"]
    128 
    129     part["history"] = [dict(zip(h.keys(), h)) for h in history]
    130 
    131     print(json.dumps({"part": part}))
    132 
    133 
    134 def _sanitize_value(value):
    135     if value is None:
    136         return "-"
    137     return value
    138 
    139 
    140 def open_file(content, extension):
    141     with tempfile.NamedTemporaryFile(suffix=extension) as f:
    142         f.write(content)
    143         subprocess.Popen(["xdg-open", f.name], start_new_session=True)
    144         time.sleep(2)
    145 
    146 
    147 def html_main_index(dest_folder, categories, storages, env):
    148     tpl = env.get_template("index.html")
    149     with open(f"{dest_folder}/index.html", "w") as f:
    150         f.write(
    151             tpl.render(
    152                 cat=categories,
    153                 sto=storages,
    154                 time_generated=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
    155             )
    156         )
    157 
    158 
    159 def html_category_index(dest_folder, category, parts, env):
    160     tpl = env.get_template("cat.html")
    161     with open(f"{dest_folder}/cat_list_{category['id']}.html", "w") as f:
    162         f.write(
    163             tpl.render(
    164                 category=category,
    165                 parts=parts,
    166                 time_generated=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
    167             )
    168         )
    169 
    170 
    171 def html_storage_index(dest_folder, storage, parts, env):
    172     tpl = env.get_template("storage.html")
    173     with open(f"{dest_folder}/storage_{storage['id']}.html", "w") as f:
    174         f.write(
    175             tpl.render(
    176                 storage=storage,
    177                 parts=parts,
    178                 time_generated=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
    179             )
    180         )
    181 
    182 
    183 def html_part(dest_folder, part, part_history, env):
    184     tpl = env.get_template("part.html")
    185     with open(f"{dest_folder}/part_{part['id']}.html", "w") as f:
    186         f.write(
    187             tpl.render(
    188                 part=part,
    189                 history=part_history,
    190                 time_generated=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
    191             )
    192         )
    193 
    194 
    195 def html_css(dest_folder, env):
    196     tpl = env.get_template("style.css")
    197     with open(f"{dest_folder}/style.css", "w") as f:
    198         f.write(tpl.render())
    199 
    200 
    201 def html_aux_files(dest_folder):
    202     orig_folder = list(exports.__path__)[0]
    203     aux_files = listdir(f"{orig_folder}/files")
    204     for f in aux_files:
    205         shutil.copy2(f"{orig_folder}/files/{f}", dest_folder)
    206 
    207 
    208 def html_attachments(dest_folder, part_id, datasheet, image):
    209     if datasheet["datasheet"] is not None:
    210         with open(f"{dest_folder}/part_datasheet_{part_id}.pdf", "wb") as f:
    211             f.write(datasheet["datasheet"])
    212     if image["image"] is not None:
    213         with open(f"{dest_folder}/part_image_{part_id}.jpg", "wb") as f:
    214             f.write(image["image"])