def test_supplier_part_create(self): """ Test that we can create SupplierPart objects via the API """ supplier = company.Company(self.api, 1) # Find a purchaseable part parts = Part.list(self.api, purchasable=True) if len(parts) > 0: prt = parts[0] else: prt = Part.create( self.api, { 'name': 'My purchaseable part', 'description': 'A purchasenable part we can use to make a SupplierPart', 'category': 1, 'purchaseable': True }) n = len(company.SupplierPart.list(self.api)) supplier_part = company.SupplierPart.create(self.api, { 'supplier': supplier.pk, 'SKU': f'SKU_TEST_{n}', 'part': prt.pk, }) self.assertIsNotNone(supplier_part) self.assertTrue(supplier_part.part, prt.pk) self.assertEqual(len(company.SupplierPart.list(self.api)), n + 1)
def find_part_location(part_number): """ find part location in database :param part_number: part number to find :return: location of the part """ try: api = InvenTreeAPI(SERVER_ADDRESS, token=My_TOKEN, verbose=True) parts = Part.list(api, search=part_number) # print(len(parts)) if len(parts) == 1: my_part = parts[0].pk elif len(parts) > 1: for part in parts: my_part = part.pk # get internal part number part_count = part._data['in_stock'] # total qty in stock part = Part(api, my_part) stock_items = part.getStockItems() if stock_items: if stock_items[0]._data['location']: stock_location = stock_items[0]._data['location'] location = inventree.stock.StockLocation(api, pk=stock_location) my_location = location._data['name'] else: my_location = 'No Location' # print(my_location) return my_location except: print(api) print('Can not connect to the database')
def test_part_delete(self): """ Test we can create and delete a Part instance via the API """ n = len(Part.list(self.api)) # Create a new part # We do not specify 'active' value so it will default to True p = Part.create( self.api, { 'name': 'Delete Me', 'description': 'Not long for this world!', 'category': 1, }) self.assertIsNotNone(p) self.assertIsNotNone(p.pk) self.assertEqual(len(Part.list(self.api)), n + 1) # Cannot delete - part is 'active'! with self.assertRaises(requests.exceptions.HTTPError) as ar: response = p.delete() self.assertIn("is active: cannot delete", str(ar.exception)) p.save(data={'active': False}) response = p.delete() self.assertEqual(response.status_code, 204) # And check that the part has indeed been deleted self.assertEqual(len(Part.list(self.api)), n)
def test_part_list(self): """ Check that we can list Part objects, and apply certain filters """ parts = Part.list(self.api) self.assertTrue(len(parts) >= 19) parts = Part.list(self.api, category=5) n = len(parts) for i in range(5): prt = Part.create( self.api, { "category": 5, "name": f"Special Part {n+i}", "description": "A new part in this category!", }) self.assertEqual(prt.category, 5) cat = prt.getCategory() self.assertEqual(cat.pk, 5) parts = cat.getParts() self.assertGreaterEqual(len(parts), i + 1)
def test_access_erors(self): """ Test that errors are flagged when we try to access an invalid part """ with self.assertRaises(TypeError): Part(self.api, 'hello') with self.assertRaises(ValueError): Part(self.api, -1) # Try to access a Part which does not exist with self.assertRaises(requests.exceptions.HTTPError): Part(self.api, 9999999999999)
def test_part_attachment(self): """ Check that we can upload attachment files against the part """ prt = Part(self.api, pk=1) attachments = PartAttachment.list(self.api, part=1) for a in attachments: self.assertEqual(a.part, 1) n = len(attachments) # Test that a file upload without the required 'part' parameter fails with self.assertRaises(ValueError): PartAttachment.upload(self.api, 'test-file.txt') # Test that attempting to upload an invalid file fails with self.assertRaises(FileNotFoundError): PartAttachment.upload(self.api, 'test-file.txt', part=1) # Check that no new files have been uploaded self.assertEqual(len(PartAttachment.list(self.api, part=1)), n) # Test that we can upload a file by filename, directly from the Part instance filename = os.path.join(os.path.dirname(__file__), 'docker-compose.yml') response = prt.uploadAttachment(filename, comment='Uploading a file') self.assertIsNotNone(response) pk = response['pk'] # Check that a new attachment has been created! attachment = PartAttachment(self.api, pk=pk) self.assertTrue(attachment.is_valid()) # Download the attachment to a local file! dst = os.path.join(os.path.dirname(__file__), 'test.tmp') attachment.download(dst, overwrite=True) self.assertTrue(os.path.exists(dst)) self.assertTrue(os.path.isfile(dst)) with self.assertRaises(FileExistsError): # Attempt to download the file again, but without overwrite option attachment.download(dst)
def test_caps(self): cat = PartCategory(self.api, 6) self.assertEqual(cat.name, "Transceivers") parts = cat.getParts() n_parts = len(parts) for p in parts: self.assertEqual(p.category, cat.pk) # Create some new parts for i in range(10): name = f"Part_{cat.pk}_{n_parts + i}" prt = Part.create( self.api, { "category": cat.pk, "name": name, "description": "A new part in this category", }) self.assertIsNotNone(prt) self.assertEqual(prt.name, name) parts = cat.getParts() self.assertEqual(len(parts), n_parts + 10)
def create_part(category_id: int, name: str, description: str, revision: str, image: str, keywords=None) -> int: ''' Create InvenTree part ''' global inventree_api part = Part.create( inventree_api, { 'name': name, 'description': description, 'category': category_id, 'keywords': keywords, 'revision': revision, 'active': True, 'virtual': False, 'component': True, 'purchaseable': True, }) if part: return part.pk else: return 0
def upload_part_image(image_url: str, part_id: int) -> bool: ''' Upload InvenTree part thumbnail''' global inventree_api # Get image full path image_name = f'{str(part_id)}_thumbnail.jpeg' image_location = settings.search_images + image_name # Download image (multiple attempts) if not download_image(image_url, image_location): return False # Upload image to InvenTree part = Part(inventree_api, part_id) if part: return part.upload_image(image=image_location) else: return False
def test_default_values(self): """ Test that the DRF framework will correctly insert the default values """ n = len(Part.list(self.api)) # Create a part without specifying 'active' and 'virtual' fields p = Part.create( self.api, { 'name': f"Part_{n}_default_test", 'category': 1, 'description': "Some part thingy", }) self.assertEqual(p.active, True) self.assertEqual(p.virtual, False) # Set both to false p = Part.create( self.api, { 'name': f"Part_{n}_default_test_2", 'category': 1, 'description': 'Setting fields to false', 'active': False, 'virtual': False, }) self.assertFalse(p.active) self.assertFalse(p.virtual) # Set both to true p = Part.create( self.api, { 'name': f"Part_{n}_default_test_3", 'category': 1, 'description': 'Setting fields to true', 'active': True, 'virtual': True, }) self.assertTrue(p.active) self.assertTrue(p.virtual)
def create_inventree_part(dkpart: DigiPart): category = find_category() possible_parts = Part.list(API, name=dkpart.name, description=dkpart.description) if len(possible_parts) > 0: part_names = [p.name.lower() for p in possible_parts] if dkpart.name.lower() in part_names: print("Part already exists") return -1 part = Part.create(API, { 'name': dkpart.name, 'description': dkpart.description, 'category': category.pk, 'active': True, 'virtual': False, 'component': True, 'purchaseable': 1 }) upload_picture(dkpart, part) return part
def create_parameter(part_id: int, template_name: int, value: str): ''' Create InvenTree part parameter based on template ''' global inventree_api parameter_template_list = ParameterTemplate.list(inventree_api) template_id = 0 for item in parameter_template_list: if template_name == item.name: template_id = item.pk break # Check if template_id already exists for this part part = Part(inventree_api, part_id) part_parameters = part.getParameters() is_new_part_parameters_template_id = True for item in part_parameters: # cprint(f'[TREE]\t{parameter.template} ?= {template_id}', silent=SILENT) if item.template == template_id: is_new_part_parameters_template_id = False break # cprint(part_parameters, silent=SILENT) ''' Create parameter only if: - template exists - parameter does not exist for this part ''' parameter = None if template_id > 0 and is_new_part_parameters_template_id: parameter = Parameter.create(inventree_api, { 'part': part_id, 'template': template_id, 'data': value, }) if parameter: return parameter.pk, is_new_part_parameters_template_id else: if template_id == 0: cprint( f'[TREE]\tError: Parameter template "{template_name}" does not exist', silent=settings.SILENT) return 0, False
def test_fields(self): """ Test field names via OPTIONS request """ field_names = Part.fieldNames(self.api) self.assertIn('active', field_names) self.assertIn('revision', field_names) self.assertIn('full_name', field_names) self.assertIn('IPN', field_names)
def createITPart(part,ITCat): print("create part %s cat %s" % (part,ITCat.name)) if len(part.description)==0: part.description=part.name np = Part.create(api, { 'name' : part.name, 'description' : part.description, 'category' : ITCat.pk, 'active' : True, 'virtual' : False, 'IPN' : part.IPN }) return np
def test_image_upload(self): """ Test image upload functionality for Part model """ # Grab the first part p = Part.list(self.api)[0] # Ensure the part does *not* have an image associated with it p.save(data={'image': None}) # Create a dummy file (not an image) with open('dummy_image.jpg', 'w') as dummy_file: dummy_file.write("hello world") # Attempt to upload an image with self.assertRaises(requests.exceptions.HTTPError): response = p.uploadImage("dummy_image.jpg") # Now, let's actually upload a real image img = Image.new('RGB', (128, 128), color='red') img.save('dummy_image.png') response = p.uploadImage("dummy_image.png") self.assertIsNotNone(response) self.assertIsNotNone(p['image']) self.assertIn('dummy_image', p['image']) # Re-download the image file fout = 'test/output.png' if os.path.exists(fout): # Delete the file if it already exists os.remove(fout) response = p.downloadImage(fout) self.assertTrue(response) self.assertTrue(os.path.exists(fout)) # Attempt to re-download with self.assertRaises(FileExistsError): p.downloadImage(fout) # Download, with overwrite enabled p.downloadImage(fout, overwrite=True)
def delete_part(part_id: int) -> bool: ''' Delete InvenTree part (only used for testing) ''' global inventree_api part = Part(inventree_api, part_id) if part.pk: part._data['active'] = False part.save() return part.delete() else: return True
def set_part_number(part_id: int, ipn: str) -> bool: ''' Set InvenTree part number for specified Part ID ''' global inventree_api part = Part(inventree_api, part_id) part._data['IPN'] = ipn part.save() if Part(inventree_api, part_id).IPN == ipn: return True else: return False
def test_part_edit(self): """ Test that we can edit a part """ # Select a part p = Part.list(self.api)[-1] name = p.name # Ajdust the name if len(name) < 40: name += '_append' else: name = name[:-10] p.save(data={'name': name, 'description': 'A new description'}, ) p.reload() self.assertEqual(p.name, name) self.assertEqual(p.description, 'A new description')
def delete_part(part_id: int) -> bool: ''' Delete InvenTree part (only used for testing) ''' global inventree_api part = Part(inventree_api, part_id) if part.pk: part._data['active'] = False # Remove image url (API rejects it as it is not a file) try: del part._data['image'] except: pass part.save() return part.delete() else: return True
def test_internal_price_create(self): """ Tests the ability to create an internal price """ p = Part.create(self.api, { 'name': 'Test Part', 'description': 'Test Part', 'category': 1, 'revision': 1, 'active': True, }) self.assertIsNotNone(p) self.assertIsNotNone(p.pk) ip = InternalPrice.create(self.api, { 'part': p.pk, 'quantity': 1, 'price': '1.00' }) self.assertIsNotNone(ip)
def test_set_price(self): """ Tests that an internal price can be set for a part """ test_price = 100.0 test_quantity = 1 # Grab the first part p = Part.list(self.api)[0] # Grab all internal prices for the part ip = InternalPrice.list(self.api, part=p.pk) # Delete any existsing prices for price in ip: self.assertEqual(type(price), InternalPrice) price.delete() # Ensure that no part has an internal price ip = InternalPrice.list(self.api, part=p.pk) self.assertEqual(len(ip), 0) # Set the internal price p.setInternalPrice(test_quantity, test_price) # Ensure that the part has an internal price ip = InternalPrice.list(self.api, part=p.pk) self.assertEqual(len(ip), 1) # Grab the internal price ip = ip[0] self.assertEqual(ip.quantity, test_quantity) self.assertEqual(ip.part, p.pk) ip_price_clean = float(ip.price) self.assertEqual(ip_price_clean, test_price)
import partkeepr from inventree.api import InvenTreeAPI from inventree.part import PartCategory,Part from inventree.stock import StockItem, StockLocation SERVER_ADDRESS = 'http://127.0.0.1:8000' MY_USERNAME = '******' MY_PASSWORD = '******' api = InvenTreeAPI(SERVER_ADDRESS, username=MY_USERNAME, password=MY_PASSWORD) #delete all the exisiting parts itparts = Part.list(api) for p in itparts: print("delete p ",p.name) p._data['active'] = False p.save() p.delete() #delete all of the exisitng categories cat = PartCategory.list(api) for c in cat: print("delete c ",c.name) c.delete()
category = 6 packages = [ '0402', '0603', '0805', ] values = [ # '100pF', '100nF', '1uF', '10uF', ] for package in packages: for value in values: name = f"C_{value}_{package}" description = f"{value} in {package} SMD package" keywords = "cap smd ceramic" Part.create(api, data={ 'name': name, 'category': category, 'description': description, 'keywords': keywords, 'purchaseable': True, })
from inventree.api import InvenTreeAPI from inventree.part import Part, PartCategory from inventree.stock import StockItem, StockLocation from inventree.company import SupplierPart import random import sys INVENTREE_URL = "http://localhost:8000" INVENTREE_USERNAME = "******" INVENTREE_PASSWORD = "******" api = InvenTreeAPI(INVENTREE_URL, username=INVENTREE_USERNAME, password=INVENTREE_PASSWORD) resistors = Part.list(api, category=5) storage = StockLocation(api, pk=8) count = 0 for resistor in resistors: if random.random() > 0.65: continue q = random.random() quantity = 1000 if q < 0.1:
def test_parameters(self): """ Test setting and getting Part parameter templates, as well as parameter values """ # Count number of existing Parameter Templates existingTemplates = len(ParameterTemplate.list(self.api)) # Create new parameter template - this will fail, no name given parametertemplate = ParameterTemplate.create(self.api, data={'units': "kg A"}) # result should be None self.assertIsNone(parametertemplate) # Now create a proper parameter template parametertemplate = ParameterTemplate.create( self.api, data={ 'name': f'Test parameter no {existingTemplates}', 'units': "kg A" }) # result should not be None self.assertIsNotNone(parametertemplate) # Count should be one higher now self.assertEqual(len(ParameterTemplate.list(self.api)), existingTemplates + 1) # Grab the first part p = Part.list(self.api)[0] # Count number of parameters existingParameters = len(p.getParameters()) # Define parameter value for this part - without all required values param = Parameter.create(self.api, data={ 'part': p.pk, 'template': parametertemplate.pk }) # result should be None self.assertIsNone(param) # Define parameter value for this part - without all required values param = Parameter.create(self.api, data={'part': p.pk, 'data': 10}) # result should be None self.assertIsNone(param) # Define w. required values - integer param = Parameter.create(self.api, data={ 'part': p.pk, 'template': parametertemplate.pk, 'data': 10 }) # result should not be None self.assertIsNotNone(param) # Same parameter for same part - should fail # Define w. required values - string param2 = Parameter.create(self.api, data={ 'part': p.pk, 'template': parametertemplate.pk, 'data': 'String value' }) # result should be None self.assertIsNone(param2) # Number of parameters should be one higher than before self.assertEqual(len(p.getParameters()), existingParameters + 1) # Delete the parameter param.delete() # Check count self.assertEqual(len(p.getParameters()), existingParameters)
def get_part_number(part_id: int) -> str: ''' Get InvenTree part number from specified Part ID ''' global inventree_api part = Part(inventree_api, part_id) return part.IPN
from digikey.v3.productinformation import KeywordSearchRequest os.environ['DIGIKEY_CLIENT_ID'] = 'DjV4w1v0ebNTiL7Nqvslw0GkNYuYdrLG' os.environ['DIGIKEY_CLIENT_SECRET'] = 'dK0dTRimeq3aiPH1' os.environ['DIGIKEY_CLIENT_SANDBOX'] = 'False' os.environ['DIGIKEY_STORAGE_PATH'] = 'C:\\Users\\Oliver\\Desktop\\digikey\\' INVENTREE_URL = "http://localhost:8000" INVENTREE_USERNAME = "******" INVENTREE_PASSWORD = "******" inventree = InvenTreeAPI(INVENTREE_URL, username=INVENTREE_USERNAME, password=INVENTREE_PASSWORD) resistors = Part.list(inventree, category=5) def getParameter(result, name): for param in result.parameters: if param.parameter.lower() == name.lower(): return param return None def getValue(result, name): param = getParameter(result, name)
from inventree.part import Part, PartCategory from inventree.stock import StockItem, StockLocation from inventree.company import SupplierPart import random import sys INVENTREE_URL = "http://localhost:8000" INVENTREE_USERNAME = "******" INVENTREE_PASSWORD = "******" api = InvenTreeAPI(INVENTREE_URL, username=INVENTREE_USERNAME, password=INVENTREE_PASSWORD) capacitors = Part.list(api, category=6) storage = StockLocation(api, pk=8) count = 0 for cap in capacitors: if random.random() > 0.65: continue # Get the first matching supplierpart sp_list = SupplierPart.list(api, part=cap.pk) for sp in sp_list: if random.random() > 0.6: