Stripping all instances of a string from a string in python - python

I have some results from a custom API that I need to parse and clean up. below is a sample output that is stored as a variable.
(DeviceConnectionInformation){
DeviceName = "device1"
ClientName = "ourclient"
RegionName = "west"
PrimaryIP = "1.1.1.1"
OsVersionName = "Microsoft Windows 7 Enterprise"
AccessMethod = None
AccessIP = None
Port = None
},
(DeviceConnectionInformation){
DeviceName = "device2"
ClientName = "ourclient"
RegionName = None
PrimaryIP = "1.1.1.2"
OsVersionName = "Microsoft Windows 7 Enterprise"
AccessMethod = None
AccessIP = None
Port = None
I need to strip any and all occurences of "(DeviceConnectionInformation){" and "}," that might occur, and leave the below format:
DeviceName = "device1"
ClientName = "ourclient"
RegionName = "west"
PrimaryIP = "1.1.1.1"
OsVersionName = "Microsoft Windows 7 Enterprise"
AccessMethod = None
AccessIP = None
Port = None
DeviceName = "device2"
ClientName = "ourclient"
RegionName = None
PrimaryIP = "1.1.1.2"
OsVersionName = "Microsoft Windows 7 Enterprise"
AccessMethod = None
AccessIP = None
Port = None

Assuming your data is in string form, you can strip a literal string by replacing it with nothing:
val = val.replace("(DeviceConnectionInformation){", "")
val = val.replace("},", "")
However, I'd be cautious about this, especially the second case, because it pays no attention to the context. For instance, if }, occurs inside a quoted string your data, it will still be removed.

How about
for x in ("DevicConnectionInformation{\n", "},", " "):
data = data.replace(x, "")
of you get into trouble if, e.g., }, appears in the values.

Related

Python Json value overwritten by last value

lista =
[{Identity: joe,
summary:[
{distance: 1, time:2, status: idle},
{distance:2, time:5, status: moving}],
{unit: imperial}]
I can pull the data easily and put in pandas. The issue is, if an identity has multiple instances of, say idle, it takes the last value, instead of summing together.
my code...
zdrivershours = {}
zdistance = {}
zstophours = {}
For driver in resp:
driverid[driver['AssetID']] = driver['AssetName']
for value in [driver['SegmentSummary']]:
for value in value:
if value['SegmentType'] == 'Motion':
zdriverhours[driver['AssetID']] = round(value['Time']/3600,2)
if value['SegmentType'] == 'Stop':
zstophours[driver['AssetID']] = round(value['IdleTime']/3600,2)
zdistance[driver['AssetID']] = value['Distance']
To obtain the summatory of distance for every driver replace:
zdistance[driver['AssetID']] = value['Distance']
by
if driver['AssetID'] in zdistance:
zdistance[driver['AssetID']] = zdistance[driver['AssetID']] + value['Distance']
else:
zdistance[driver['AssetID']] = value['Distance']

How to add customs value in python-fedex for international shipments?

I'm using the python-fedex module as a light wrapper for the FedEx SOAP API. As part of this, I'm trying to set up a basic example of an international shipment, but I'm getting stuck with the following error message:
fedex.base_service.FedexError: Customs Value is required. (Error code: 2033)
I believe I need to add the products I ship as commodities, incl. their customs value - but I struggle to get this to work. I found this link with some guidance (from C#), but I was unable to get it to work in Python. Any inputs are appreciated!
My code is below:
# !/usr/bin/env python
"""
This example shows how to create a shipment and generate a waybill as output. The variables populated below
represents the minimum required values. You will need to fill all of these, or
risk seeing a SchemaValidationError exception thrown.
Near the bottom of the module, you'll see some different ways to handle the
label data that is returned with the reply.
"""
import logging
import binascii
import datetime
import sys, os
from example_config import CONFIG_OBJ
from fedex.services.ship_service import FedexProcessShipmentRequest
# What kind of file do you want this example to generate?
# Valid choices for this example are PDF, PNG
GENERATE_IMAGE_TYPE = 'PDF'
# Un-comment to see the response from Fedex printed in stdout.
logging.basicConfig(stream=sys.stdout, level=logging.INFO)
# This is the object that will be handling our shipment request.
# We're using the FedexConfig object from example_config.py in this dir.
customer_transaction_id = "*** ShipService Request v17 using Python ***" # Optional transaction_id
shipment = FedexProcessShipmentRequest(CONFIG_OBJ, customer_transaction_id=customer_transaction_id)
# This is very generalized, top-level information.
# REGULAR_PICKUP, REQUEST_COURIER, DROP_BOX, BUSINESS_SERVICE_CENTER or STATION
shipment.RequestedShipment.DropoffType = 'BUSINESS_SERVICE_CENTER'
# See page 355 in WS_ShipService.pdf for a full list. Here are the common ones:
# STANDARD_OVERNIGHT, PRIORITY_OVERNIGHT, FEDEX_GROUND, FEDEX_EXPRESS_SAVER,
# FEDEX_2_DAY, INTERNATIONAL_PRIORITY, SAME_DAY, INTERNATIONAL_ECONOMY
shipment.RequestedShipment.ServiceType = 'INTERNATIONAL_PRIORITY'
# What kind of package this will be shipped in.
# FEDEX_BOX, FEDEX_PAK, FEDEX_TUBE, YOUR_PACKAGING, FEDEX_ENVELOPE
shipment.RequestedShipment.PackagingType = 'FEDEX_ENVELOPE'
# Shipper contact info.
shipment.RequestedShipment.Shipper.Contact.PersonName = 'Shipper Name'
shipment.RequestedShipment.Shipper.Contact.CompanyName = 'Shipper Company'
shipment.RequestedShipment.Shipper.Contact.PhoneNumber = '004512345678'
# Shipper address.
shipment.RequestedShipment.Shipper.Address.StreetLines = ['Shipper Address']
shipment.RequestedShipment.Shipper.Address.City = 'City'
shipment.RequestedShipment.Shipper.Address.StateOrProvinceCode = ''
shipment.RequestedShipment.Shipper.Address.PostalCode = '8270'
shipment.RequestedShipment.Shipper.Address.CountryCode = 'DK'
shipment.RequestedShipment.Shipper.Address.Residential = False
# Recipient contact info.
shipment.RequestedShipment.Recipient.Contact.PersonName = 'US customer X'
shipment.RequestedShipment.Recipient.Contact.CompanyName = 'US company X'
shipment.RequestedShipment.Recipient.Contact.PhoneNumber = '0123456789'
# Recipient address
shipment.RequestedShipment.Recipient.Address.StreetLines = ['668 MURRAY AVE SE']
shipment.RequestedShipment.Recipient.Address.City = 'ROANOKE'
shipment.RequestedShipment.Recipient.Address.StateOrProvinceCode = 'VA'
shipment.RequestedShipment.Recipient.Address.PostalCode = '24013'
shipment.RequestedShipment.Recipient.Address.CountryCode = 'US'
# This is needed to ensure an accurate rate quote with the response. Use AddressValidation to get ResidentialStatus
shipment.RequestedShipment.Recipient.Address.Residential = False
shipment.RequestedShipment.EdtRequestType = 'NONE'
# Senders account information
shipment.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.AccountNumber = CONFIG_OBJ.account_number
# Who pays for the shipment?
# RECIPIENT, SENDER or THIRD_PARTY
shipment.RequestedShipment.ShippingChargesPayment.PaymentType = 'SENDER'
# Specifies the label type to be returned.
# LABEL_DATA_ONLY or COMMON2D
shipment.RequestedShipment.LabelSpecification.LabelFormatType = 'COMMON2D'
# Specifies which format the label file will be sent to you in.
# DPL, EPL2, PDF, PNG, ZPLII
shipment.RequestedShipment.LabelSpecification.ImageType = GENERATE_IMAGE_TYPE
# To use doctab stocks, you must change ImageType above to one of the
# label printer formats (ZPLII, EPL2, DPL).
# See documentation for paper types, there quite a few.
shipment.RequestedShipment.LabelSpecification.LabelStockType = 'PAPER_7X4.75'
# This indicates if the top or bottom of the label comes out of the
# printer first.
# BOTTOM_EDGE_OF_TEXT_FIRST or TOP_EDGE_OF_TEXT_FIRST
# Timestamp in YYYY-MM-DDThh:mm:ss format, e.g. 2002-05-30T09:00:00
shipment.RequestedShipment.ShipTimestamp = datetime.datetime.now().replace(microsecond=0).isoformat()
# BOTTOM_EDGE_OF_TEXT_FIRST, TOP_EDGE_OF_TEXT_FIRST
shipment.RequestedShipment.LabelSpecification.LabelPrintingOrientation = 'TOP_EDGE_OF_TEXT_FIRST'
# Delete the flags we don't want.
# Can be SHIPPING_LABEL_FIRST, SHIPPING_LABEL_LAST or delete
if hasattr(shipment.RequestedShipment.LabelSpecification, 'LabelOrder'):
del shipment.RequestedShipment.LabelSpecification.LabelOrder # Delete, not using.
# Create Weight, in pounds.
package1_weight = shipment.create_wsdl_object_of_type('Weight')
package1_weight.Value = 1.0
package1_weight.Units = "LB"
# Create PackageLineItem
package1 = shipment.create_wsdl_object_of_type('RequestedPackageLineItem')
# BAG, BARREL, BASKET, BOX, BUCKET, BUNDLE, CARTON, CASE, CONTAINER, ENVELOPE etc..
package1.PhysicalPackaging = 'ENVELOPE'
package1.Weight = package1_weight
# Add a signature option for the package using SpecialServicesRequested or comment out.
# SpecialServiceTypes can be APPOINTMENT_DELIVERY, COD, DANGEROUS_GOODS, DRY_ICE, SIGNATURE_OPTION etc..
package1.SpecialServicesRequested.SpecialServiceTypes = 'SIGNATURE_OPTION'
# SignatureOptionType can be ADULT, DIRECT, INDIRECT, NO_SIGNATURE_REQUIRED, SERVICE_DEFAULT
package1.SpecialServicesRequested.SignatureOptionDetail.OptionType = 'SERVICE_DEFAULT'
# This adds the RequestedPackageLineItem WSDL object to the shipment. It
# increments the package count and total weight of the shipment for you.
shipment.add_package(package1)
# If you want to make sure that all of your entered details are valid, you
# can call this and parse it just like you would via send_request(). If
# shipment.response.HighestSeverity == "SUCCESS", your shipment is valid.
# print(shipment.send_validation_request())
# Fires off the request, sets the 'response' attribute on the object.
shipment.send_request()
Your need to add more information.
Insert the following codes before shipment.send_request(), then try again.
shipment.RequestedShipment.CustomsClearanceDetail.CustomsValue.Currency = 'USD'
shipment.RequestedShipment.CustomsClearanceDetail.CustomsValue.Amount = 1.0
shipment.RequestedShipment.CustomsClearanceDetail.DutiesPayment.PaymentType = 'SENDER'
shipment.RequestedShipment.CustomsClearanceDetail.DutiesPayment.Payor.ResponsibleParty.AccountNumber = CONFIG_OBJ.account_number
commodity1 = shipment.create_wsdl_object_of_type('Commodity')
commodity1.Name = 'book'
commodity1.NumberOfPieces = 1
commodity1.Description = '1'
commodity1.CountryOfManufacture = 'CN'
commodity1.HarmonizedCode = '123456789'
commodity1.Quantity = 1.0
commodity1.QuantityUnits = 'EA'
commodity1.Weight.Value = 1.0
commodity1.Weight.Units = "LB"
commodity1.CustomsValue.Currency = 'USD'
commodity1.CustomsValue.Amount = 1.0
commodity1.UnitPrice.Currency = 'USD'
commodity1.UnitPrice.Amount = 1.0
shipment.RequestedShipment.CustomsClearanceDetail.Commodities = [commodity1]
I have added a full international shipment example below, which solves this:
"""
This example shows how to create an international shipment and generate a waybill as output.
The example takes outset in a real practical use case, where electronic trade documents are
used and an existing PDF commercial invoice is added along with product descriptions via ETD.
Further, it adds event notifications to allow for emails to be sent to the end recipient.
The script is comprised of a FedExLabelHelper class with all core functions, and a use case
example with minimal dummy data
"""
from example_config import CONFIG_OBJ
from pathlib import Path
import binascii
import datetime
from fedex.services.ship_service import FedexProcessShipmentRequest
# ----------------------------------------------------
# FedEx class for creating shipments
class FedexLabelHelper:
mCommodities = []
def __init__(self):
pass
# ----------------------------------------------------
# set overall shipment configuration
def setShipmentConfig(
self,
CONFIG_OBJ,
invoice_info,
cust_tran_id="*** ShipService Request v17 using Python ***",
dropoffType="BUSINESS_SERVICE_CENTER",
shippingPaymentType="SENDER",
labelFormatType="COMMON2D",
labelSpecificationImageType="PDF",
labelSpecificationStockType="PAPER_7X4.75",
labelPrintingOrientation="TOP_EDGE_OF_TEXT_FIRST",
LabelOrder="SHIPPING_LABEL_FIRST",
):
self.invoice_info = invoice_info
self.dropoffType = dropoffType
self.serviceType = "INTERNATIONAL_PRIORITY" if invoice_info["ShippingExpress"] == True else "INTERNATIONAL_ECONOMY"
self.mCommodities.clear()
self.CONFIG_OBJ = CONFIG_OBJ
self.shipment = FedexProcessShipmentRequest(CONFIG_OBJ, customer_transaction_id=cust_tran_id)
self.shipment.RequestedShipment.DropoffType = dropoffType
self.shipment.RequestedShipment.ServiceType = self.serviceType
self.shipment.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.AccountNumber = CONFIG_OBJ.account_number
self.shipment.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.Address.CountryCode = "DK"
self.shipment.RequestedShipment.ShippingChargesPayment.PaymentType = shippingPaymentType
labelSpecification = self.shipment.create_wsdl_object_of_type("LabelSpecification")
labelSpecification.LabelFormatType = labelFormatType
labelSpecification.LabelStockType = labelSpecificationStockType
labelSpecification.ImageType = labelSpecificationImageType
labelSpecification.LabelOrder = LabelOrder
labelSpecification.LabelPrintingOrientation = labelPrintingOrientation
self.shipment.RequestedShipment.LabelSpecification = labelSpecification
# ----------------------------------------------------
# set sender information
def setSenderInfo(self, sender):
self.shipment.RequestedShipment.Shipper.Contact.PersonName = sender["Name"]
self.shipment.RequestedShipment.Shipper.Contact.CompanyName = sender["Company"]
self.shipment.RequestedShipment.Shipper.Contact.PhoneNumber = sender["Phone"]
self.shipment.RequestedShipment.Shipper.Contact.EMailAddress = sender["Email"]
self.shipment.RequestedShipment.Shipper.Address.StreetLines = sender["Address"]
self.shipment.RequestedShipment.Shipper.Address.City = sender["City"]
self.shipment.RequestedShipment.Shipper.Address.StateOrProvinceCode = sender["Region"]
self.shipment.RequestedShipment.Shipper.Address.PostalCode = sender["Zip"]
self.shipment.RequestedShipment.Shipper.Address.CountryCode = sender["CountryCode"]
self.shipment.RequestedShipment.Shipper.Address.Residential = sender["Residential"]
ti = self.shipment.create_wsdl_object_of_type("TaxpayerIdentification")
ti.Number = sender["VAT"]
ti.TinType = "BUSINESS_NATIONAL"
self.shipment.RequestedShipment.Shipper.Tins = ti
# ----------------------------------------------------
# upload all documents (invoice and product information)
def upload_all_documents(self):
doc_ids = []
doc_ids.append(self.upload_document(self.invoice_info["InvoicePath"], "COMMERCIAL_INVOICE"))
for pdf in self.invoice_info["Pdfs"]:
doc_ids.append(self.upload_document(pdf, "OTHER"))
return doc_ids
# ----------------------------------------------------
# function for uploading documents as electronic trade documents and getting the response doc IDs
def upload_document(self, path, type):
from fedex.services.document_service import FedexDocumentServiceRequest
# specify prefix for use in attachment naming
if type == "COMMERCIAL_INVOICE":
prefix = "invoice_"
else:
prefix = "product_description_"
uploadRequest = FedexDocumentServiceRequest(self.CONFIG_OBJ)
uploadRequest.OriginCountryCode = "DK"
uploadRequest.DestinationCountryCode = self.shipment.RequestedShipment.Recipient.Address.CountryCode
uploadRequest.Usage = "ELECTRONIC_TRADE_DOCUMENTS"
clientdetails = uploadRequest.create_wsdl_object_of_type("ClientDetail")
clientdetails.AccountNumber = self.CONFIG_OBJ.account_number
clientdetails.MeterNumber = self.CONFIG_OBJ.meter_number
uploadRequest.ClientDetail = clientdetails
webAuthDetails = uploadRequest.create_wsdl_object_of_type("WebAuthenticationDetail")
webAuthDetails.ParentCredential.Key = self.CONFIG_OBJ.key
webAuthDetails.ParentCredential.Password = self.CONFIG_OBJ.password
webAuthDetails.UserCredential.Key = self.CONFIG_OBJ.key
webAuthDetails.UserCredential.Password = self.CONFIG_OBJ.password
uploadRequest.WebAuthenticationDetail = webAuthDetails
docdetails = uploadRequest.create_wsdl_object_of_type("UploadDocumentDetail")
docdetails.LineNumber = 1
docdetails.DocumentType = type
docdetails.FileName = prefix + path
fileContent = open(path, "rb").read()
fileBase64 = binascii.b2a_base64(fileContent)
docdetails.DocumentContent = fileBase64.decode("cp1250")
uploadRequest.Documents = docdetails
uploadRequest.send_request()
doc_id = uploadRequest.response.DocumentStatuses[0].DocumentId
return doc_id
# ----------------------------------------------------
# set recipient information
def setRecipientInfo(self, recipient):
self.shipment.RequestedShipment.Recipient.Contact.PersonName = recipient["Name"]
self.shipment.RequestedShipment.Recipient.Contact.CompanyName = recipient["Company"]
self.shipment.RequestedShipment.Recipient.Contact.PhoneNumber = recipient["Phone"]
self.shipment.RequestedShipment.Recipient.Contact.EMailAddress = recipient["Email"]
self.shipment.RequestedShipment.Recipient.Address.StreetLines = recipient["Address"]
self.shipment.RequestedShipment.Recipient.Address.City = recipient["City"]
self.shipment.RequestedShipment.Recipient.Address.StateOrProvinceCode = recipient["Region"]
self.shipment.RequestedShipment.Recipient.Address.PostalCode = recipient["Zip"]
self.shipment.RequestedShipment.Recipient.Address.CountryCode = recipient["CountryCode"]
self.shipment.RequestedShipment.Recipient.Address.Residential = recipient["Residential"]
ti = self.shipment.create_wsdl_object_of_type("TaxpayerIdentification")
ti.Number = recipient["VAT"]
ti.TinType = "BUSINESS_NATIONAL"
self.shipment.RequestedShipment.Recipient.Tins = ti
# ----------------------------------------------------
# add "commercial invoice" reference as the only commodity
def add_ci_commodity(self):
self.addCommodity(
cCustomsValueAmnt=self.invoice_info["Value"],
cCustomsValueCurrency=self.invoice_info["Currency"],
cWeightValue=self.invoice_info["Weight"],
cDescription="See attached commercial invoice",
cQuantity=self.invoice_info["Quantity"],
cExportLicenseNumber=self.shipment.RequestedShipment.Shipper.Tins.Number,
cPartNumber=1,
)
# ----------------------------------------------------
# add commodity to shipment (for now, just add 1 commodity to refer to attached CI)
def addCommodity(
self, cCustomsValueAmnt, cCustomsValueCurrency, cWeightValue, cDescription, cQuantity, cExportLicenseNumber, cPartNumber,
):
commodity = self.shipment.create_wsdl_object_of_type("Commodity")
commodity.NumberOfPieces = str(cQuantity)
commodity.Description = cDescription
commodity.Quantity = cQuantity
commodity.QuantityUnits = "EA"
commodity.ExportLicenseNumber = cExportLicenseNumber
commodity.PartNumber = cPartNumber
commodity.CountryOfManufacture = "DK"
mCustomsValue = self.shipment.create_wsdl_object_of_type("Money")
mCustomsValue.Amount = cCustomsValueAmnt
mCustomsValue.Currency = cCustomsValueCurrency
commodity.CustomsValue = mCustomsValue
commodity_weight = self.shipment.create_wsdl_object_of_type("Weight")
commodity_weight.Value = cWeightValue
commodity_weight.Units = "KG"
commodity.Weight = commodity_weight
munitPrice = self.shipment.create_wsdl_object_of_type("Money")
munitPrice.Amount = float(round((cCustomsValueAmnt / cQuantity), 2))
munitPrice.Currency = cCustomsValueCurrency
commodity.UnitPrice = munitPrice
self.mCommodities.append(commodity)
# ----------------------------------------------------
# add package to shipment
def set_packaging_info(self):
weight = self.invoice_info["Weight"]
type = "BOX" if weight > 0.5 else "ENVELOPE"
weight_final = float(round(weight + 0.2, 2)) if weight > 0.5 else 0.4
self.addShippingPackage(packageWeight=weight_final, physicalPackagingType=type, packagingType=f"FEDEX_{type}")
# ----------------------------------------------------
# add package to shipment
def addShippingPackage(self, packageWeight, physicalPackagingType, packagingType, packageWeightUnit="KG"):
package_weight = self.shipment.create_wsdl_object_of_type("Weight")
package_weight.Value = packageWeight
package_weight.Units = packageWeightUnit
package = self.shipment.create_wsdl_object_of_type("RequestedPackageLineItem")
package.PhysicalPackaging = physicalPackagingType
package.Weight = package_weight
self.shipment.add_package(package)
self.shipment.RequestedShipment.TotalWeight = package_weight
self.shipment.RequestedShipment.PackagingType = packagingType
# ----------------------------------------------------
# add information on duties
def setDutiesPaymentInfo(self):
mParty = self.shipment.create_wsdl_object_of_type("Party")
mParty.AccountNumber = self.CONFIG_OBJ.account_number
mParty.Address = self.shipment.RequestedShipment.Recipient.Address
mPayor = self.shipment.create_wsdl_object_of_type("Payor")
mPayor.ResponsibleParty = mParty
mPayment = self.shipment.create_wsdl_object_of_type("Payment")
mPayment.PaymentType = "RECIPIENT" # change if sender should pay duties
mPayment.Payor = mPayor
mCustomsValue = self.shipment.create_wsdl_object_of_type("Money")
mCustomsValue.Amount = self.invoice_info["Value"]
mCustomsValue.Currency = self.invoice_info["Currency"]
ccd = self.shipment.create_wsdl_object_of_type("CustomsClearanceDetail")
ccd.Commodities = self.mCommodities
ccd.CustomsValue = mCustomsValue
ccd.DutiesPayment = mPayment
self.shipment.RequestedShipment.CustomsClearanceDetail = ccd
# ----------------------------------------------------
# Set ETD (electronic trade documents) settings
def setSpecialServices(self, doc_ids):
# construct objects
ssr = self.shipment.create_wsdl_object_of_type("ShipmentSpecialServicesRequested")
ssr.SpecialServiceTypes.append("ELECTRONIC_TRADE_DOCUMENTS")
ssr.SpecialServiceTypes.append("EVENT_NOTIFICATION")
# set up ETD details
etd = self.shipment.create_wsdl_object_of_type("EtdDetail")
etd.RequestedDocumentCopies = "COMMERCIAL INVOICE"
for i, doc_id in enumerate(doc_ids, start=0):
udrd = self.shipment.create_wsdl_object_of_type("UploadDocumentReferenceDetail")
udrd.DocumentType = "COMMERCIAL_INVOICE" if i == 0 else "OTHER"
udrd.DocumentId = doc_id
udrd.Description = "Commercial_Invoice" if i == 0 else "Product_Description"
udrd.DocumentIdProducer = "CUSTOMER"
ssr.EtdDetail.DocumentReferences.append(udrd)
self.shipment.RequestedShipment.SpecialServicesRequested = ssr
# set Event Notification details
send = self.shipment.create_wsdl_object_of_type("ShipmentEventNotificationDetail")
send.AggregationType = "PER_SHIPMENT"
sens = self.shipment.create_wsdl_object_of_type("ShipmentEventNotificationSpecification")
sens.NotificationDetail.NotificationType = "EMAIL"
sens.NotificationDetail.EmailDetail.EmailAddress = self.shipment.RequestedShipment.Recipient.Contact.EMailAddress
sens.NotificationDetail.EmailDetail.Name = self.shipment.RequestedShipment.Recipient.Contact.PersonName
sens.NotificationDetail.Localization.LanguageCode = "EN"
sens.Role = "SHIPPER"
sens.Events.append("ON_SHIPMENT")
sens.Events.append("ON_EXCEPTION")
sens.Events.append("ON_DELIVERY")
sens.FormatSpecification.Type = "HTML"
send.EventNotifications = sens
self.shipment.RequestedShipment.SpecialServicesRequested.EventNotificationDetail = send
# ----------------------------------------------------
# process the shipment
def processInternationalShipment(self):
from shutil import copyfile
self.shipment.RequestedShipment.ShipTimestamp = datetime.datetime.now().replace(microsecond=0).isoformat()
# print(" ---- **** DETAILS ---- ****")
# print(self.shipment.RequestedShipment)
# print(self.shipment.ClientDetail)
# print(self.shipment.TransactionDetail)
# print("REQUESTED SHIPMENT\n\n", self.shipment.RequestedShipment)
self.shipment.send_request()
# print("RESPONSE\n\n", self.shipment.response)
status = self.shipment.response.HighestSeverity
if status == "SUCCESS" and "CompletedShipmentDetail" in self.shipment.response:
shipment_details = self.shipment.response.CompletedShipmentDetail
package_details = shipment_details.CompletedPackageDetails[0]
tracking_id = package_details.TrackingIds[0].TrackingNumber
email = self.shipment.RequestedShipment.Recipient.Contact.EMailAddress
fedex_cost = "N/A"
if hasattr(package_details, "PackageRating"):
fedex_cost = package_details.PackageRating.PackageRateDetails[0].NetCharge.Amount
# create the shipping PDF label
ascii_label_data = package_details.Label.Parts[0].Image
label_binary_data = binascii.a2b_base64(ascii_label_data)
out_path = self.invoice_info["InvoiceId"] + f"_shipment_label_{tracking_id}.pdf"
out_file = open(out_path, "wb")
out_file.write(label_binary_data)
out_file.close()
# print output information
print(
f"- SUCCESS: Created FedEx label for invoice {self.invoice_info['InvoiceId']}\n tracking ID: {tracking_id}\n email: {email}\n FedEx cost: {fedex_cost}\n Customs value: {self.invoice_info['Value']} {self.invoice_info['Currency']}\n Weight: {self.invoice_info['Weight']}\n output path: {out_path}"
)
# ----------------------------------------------------
# main script
commercial_invoice_path = "commercial_invoice_test.pdf"
product_description_1_path = "product_description_test.pdf"
sender = {
"Company": "Sender Company",
"Name": "Mr Smith",
"Address": ["Address 1", "Address 2"],
"Region": "",
"Zip": "8230",
"City": "Abyhoj",
"Country": "Denmark",
"Phone": "12345678",
"Email": "mail#mail.com",
"CountryCode": "DK",
"Currency": "EUR",
"VAT": "DK12345678",
"Residential": False,
}
recipient = {
"Company": "Recipient Co",
"Name": "Contact Name",
"Address": ["Adr1, Adr2"],
"Region": "MN",
"Zip": "55420",
"City": "Bloomington",
"Country": "United States",
"Phone": "0123456789",
"Email": "mail#mail.com",
"CountryCode": "US",
"Currency": "EUR",
"VAT": "",
"Residential": False,
}
invoice_info = {
"InvoiceId": "14385",
"Weight": 0.11,
"Quantity": 2,
"Value": 20.0,
"Shipping": 25.0,
"ShippingExpress": True,
"Currency": "EUR",
"InvoicePath": commercial_invoice_path,
"Pdfs": [product_description_1_path],
}
# print output
print(f"\n- recipient: {recipient}\n- invoice_info: {invoice_info}\n")
# create FedEx Label Helper and set configuration
flh = FedexLabelHelper()
flh.setShipmentConfig(CONFIG_OBJ=CONFIG_OBJ, invoice_info=invoice_info)
# add sender & recipient info to FedEx shipment
flh.setSenderInfo(sender)
flh.setRecipientInfo(recipient)
# set packaging based on weight
flh.set_packaging_info()
# add reference to CI as only commodity info
flh.add_ci_commodity()
# set duties payment information
flh.setDutiesPaymentInfo()
# upload documents
doc_ids = flh.upload_all_documents()
# link uploaded documents as ETD and setup event notifications
flh.setSpecialServices(doc_ids)
# process shipments and create shipping labels
flh.processInternationalShipment()

Parsing Security Matrix Spreadsheet - NoneType is not Iterable

Trying to Nest no's and yes's with their respective applications and services.
That way when a request comes in for a specific zone to zone sequence, a check can be run against this logic to verify accepted requests.
I have tried calling Decision_List[Zone_Name][yes_no].update and i tried ,append when it was a list type and not a dict but there is no update method ?
Base_Sheet = range(5, sh.ncols)
Column_Rows = range(1, sh.nrows)
for colnum in Base_Sheet:
Zone_Name = sh.col_values(colnum)[0]
Zone_App_Header = {sh.col_values(4)[0]:{}}
Zone_Svc_Header = {sh.col_values(3)[0]:{}}
Zone_Proto_Header = {sh.col_values(2)[0]:{}}
Zone_DestPort_Header = {sh.col_values(1)[0]: {}}
Zone_SrcPort_Header = {sh.col_values(0)[0]: {}}
Decision_List = {Zone_Name:{}}
for rows in Column_Rows:
app_object = sh.col_values(4)[rows]
svc_object = sh.col_values(3)[rows]
proto_object = sh.col_values(3)[rows]
dst_object = sh.col_values(2)[rows]
src_object = sh.col_values(1)[rows]
yes_no = sh.col_values(colnum)[rows]
if yes_no not in Decision_List[Zone_Name]:
Decision_List[Zone_Name][yes_no] = [app_object]
else:
Decision_List[Zone_Name]=[yes_no].append(app_object)
I would like it present info as follows
Decision_List{Zone_Name:{yes:[ssh, ssl, soap], no:
[web-browsing,facebook]}}
I would still like to know why i couldnt call the append method on that specific yes_no key whos value was a list.
But in the mean time, i made a work around of sorts. I created a set as the key and gave the yes_no as the value. this will allow me to pair many no type values with the keys being a set of the application, port, service, etc.. and then i can search for yes values and create additional dicts out of them for logic.
Any better ideas out there i am all ears.
for rownum in range(0, sh.nrows):
#row_val is all the values in the row of cell.index[rownum] as determined by rownum
row_val = sh.row_values(rownum)
col_val = sh.col_values(rownum)
print rownum, col_val[0], col_val[1: CoR]
header.append({col_val[0]: col_val[1: CoR]})
print header[0]['Start Port']
dec_tree = {}
count = 1
Base_Sheet = range(5, sh.ncols)
Column_Rows = range(1, sh.nrows)
for colnum in Base_Sheet:
Zone_Name = sh.col_values(colnum)[0]
Zone_App_Header = {sh.col_values(4)[0]:{}}
Zone_Svc_Header = {sh.col_values(3)[0]:{}}
Zone_Proto_Header = {sh.col_values(2)[0]:{}}
Zone_DestPort_Header = {sh.col_values(1)[0]: {}}
Zone_SrcPort_Header = {sh.col_values(0)[0]: {}}
Decision_List = {Zone_Name:{}}
for rows in Column_Rows:
app_object = sh.col_values(4)[rows]
svc_object = sh.col_values(3)[rows]
proto_object = sh.col_values(3)[rows]
dst_object = sh.col_values(2)[rows]
src_object = sh.col_values(1)[rows]
yes_no = sh.col_values(colnum)[rows]
for rule_name in Decision_List.iterkeys():
Decision_List[Zone_Name][(app_object, svc_object, proto_object)]= yes_no
Thanks again.
I think still a better way is to use collections.defaultdict
In this manner it will ensure that i am able to append to the specific yes_no as i had originally intended.
for colnum in Base_Sheet:
Zone_Name = sh.col_values(colnum)[0]
Zone_App_Header = {sh.col_values(4)[0]:{}}
Zone_Svc_Header = {sh.col_values(3)[0]:{}}
Zone_Proto_Header = {sh.col_values(2)[0]:{}}
Zone_DestPort_Header = {sh.col_values(1)[0]: {}}
Zone_SrcPort_Header = {sh.col_values(0)[0]: {}}
Decision_List = {Zone_Name:defaultdict(list)}
for rows in Column_Rows:
app_object = sh.col_values(4)[rows]
svc_object = sh.col_values(3)[rows]
proto_object = sh.col_values(2)[rows]
dst_object = sh.col_values(1)[rows]
src_object = sh.col_values(0)[rows]
yes_no = sh.col_values(colnum)[rows]
if yes_no not in Decision_List[Zone_Name]:
Decision_List[Zone_Name][yes_no]= [app_object, svc_object, proto_object, dst_object, src_object]
else:
Decision_List[Zone_Name][yes_no].append([(app_object, svc_object, proto_object,dst_object, src_object)])
This allows me to then set the values as a set and append them as needed

Trying to avoid creating numerous variables in python

I am new to python and I have a lot of variables I will be using in this script. These variables are being used to grab data from each column in an uploaded file. I have added variables for each object type and I have about 12 more object types to add. Isn't there a better way I can do this? I have the file it's grabbing data from here:
Action Object Solution ID hostgroup_name alias
Add Host Group ISD-CR ISD-CR_database ISD-CR Database
Add Service ISD-CR ISD-CR_database
Update Service Group ISD-CR ISD-CR Database
Delete Service ISD-CR ISD-CR_database
Here is the script I have so far.
from pynag import Model
from pynag.Parsers import config
def addObject():
# Add hostgroup object
hg = Model.Hostgroup()
hg.set_filename('/etc/nagios/objects/solution1/{0}.cfg'.format(target_hostgroup_name))
# Adding all attributes to allow any to be added if needed
hg.hostgroup_name = target_hostgroup_name
hg.alias = target_alias
hg.members = target_members
hg.hostgroup_members = target_hostgroup_members
hg.notes = target_notes
hg.notes_url = target_notes_url
hg.action_url = target_action_url
# Save
hg.save()
print "hostgroup added"
# Add service object
s = Model.Service()
s.set_filename('/etc/nagios/objects/solution1/{0}.cfg'.format(target_hostgroup_name))
# Adding all attributes to allow any to be added if needed
s.host_name = target_host_name
s.hostgroup_name = target_hostgroup_name
s.service_description = target_service_description
s.display_name = target_display_name
s.servicegroups = target_servicegroups
s.is_volatile = target_is_volatile
s.check_command = target_check_command
s.initial_state = target_initial_state
s.max_check_attempts = target_max_check_attempts
s.check_interval = target_check_interval
s.retry_interval = target_retry_interval
s.active_checks_enabled = target_active_checks_enabled
s.passive_checks_enabled = target_passive_checks_enabled
s.check_period = target_check_period
s.obsess_over_service = target_obsess_over_service
s.check_freshness = target_check_freshness
s.freshness_threshold = target_freshness_threshold
s.event_handler = target_event_handler
s.event_handler_enabled = target_event_handler_enabled
s.low_flap_threshold = target_low_flap_threshold
s.high_flap_threshold = target_high_flap_threshold
s.flap_detection_enabled = target_flap_detection_enabled
s.flap_detection_options = target_flap_detection_options
s.process_perf_data = target_process_perf_data
s.retain_status_information = target_retain_status_information
s.retain_nonstatus_information = target_retain_nonstatus_information
s.notification_interval = target_notification_interval
s.first_notification_delay = target_first_notification_delay
s.notification_period = target_notification_period
s.notification_options = target_notification_options
s.notification_enabled = target_notifications_enabled
s.contacts = target_contacts
s.contact_groups = target_contact_groups
s.stalking_options = target_stalking_options
s.notes = target_notes
s.notes_url = target_notes_url
s.action_url = target_action_url
s.icon_image = target_icon_image
s.icon_image_alt = target_icon_image_alt
# Save
s.save()
print "service added"
# Add servicegroup object
sg = Model.Servicegroup()
sg.set_filename('/etc/nagios/objects/solution1/{0}.cfg'.format(target_hostgroup_name))
# Adding all attributes to allow any to be added if needed
sg.servicegroup_name = target_servicegroup_name
sg.alias = target_alias
sg.members = target_members
sg.servicegroup_members = target_servicegroup_members
sg.notes = target_notes
sg.notes_url = target_notes_url
sg.action_url = '/etc/nagios/objects/solution1/{0}.cfg'.format(target_hostgroup_name)
# Save
sg.save()
print "service group added"
try:
current_file = csv.reader(open(input_file, "rb"), delimiter='\t')
except:
logging.error('No such file or directory. Please try again')
else:
for line in current_file:
for row in current_file:
target_hostgroup_name = row[3]
target_alias = row[4]
target_members = row[5]
target_hostgroup_members = row[6]
target_notes = row[7]
target_notes_url = row[8]
target_action_url = row[9]
target_host_name = row[10]
target_service_description = row[11]
target_display_name = row[12]
target_servicegroups = row[13]
target_is_volatile = row[14]
target_check_command = row[15]
target_initial_state = row[16]
target_max_check_attempts = row[17]
target_check_interval = row[18]
target_retry_interval = row[19]
target_active_checks_enabled = row[20]
target_passive_checks_enabled = row[21]
target_check_period = row[22]
target_obsess_over_service = row[23]
target_check_freshness = row[24]
target_freshness_threshold = row[25]
target_event_handler = row[26]
target_event_handler_enabled = row[27]
target_low_flap_threshold = row[28]
target_high_flap_threshold = row[29]
target_flap_detection_enabled = row[30]
target_flap_detection_options = row[31]
target_process_perf_data = row[32]
target_retain_status_information = row[33]
target_retain_nonstatus_information = row[34]
target_notification_interval = row[35]
target_first_notification_delay = row[36]
target_notification_period = row[37]
target_notification_options = row[38]
target_notifications_enabled = row[39]
target_contacts = row[40]
target_contact_groups = row[41]
target_stalking_options = row[42]
target_icon_image = row[43]
target_icon_image_alt = row[44]
target_servicegroup_name = row[45]
target_servicegroup_members = row[46]
If the values are in the same order every time, you could consider populating a list that you then could loop over, instead of doing it one by one.
For the "target" portion of your script, you could nest another loop for range(3, 46) as well, and pass the index to your list instead of manually for every number from 3 to 46.
Why do you do this?
for line in current_file:
for row in current_file:
If the first row is a header row and you're skipping it on purpose, you can use a DictReader instead.
It doesn't look like you'll be able to do much to clean this up, but you could factor out each "section" into its own function:
def save_hostgroup(name, alias, members, hostgroup_members, notes, notes_url, action_url):
hg = Model.Hostgroup()
hg.set_filename('/etc/nagios/objects/solution1/{0}.cfg'.format(target_hostgroup_name))
# Adding all attributes to allow any to be added if needed
hg.hostgroup_name = target_hostgroup_name
hg.alias = target_alias
hg.members = target_members
hg.hostgroup_members = target_hostgroup_members
hg.notes = target_notes
hg.notes_url = target_notes_url
hg.action_url = target_action_url
hg.save()
Behind the scenes all the member names of an object are stored in a dict. You can access this dict with vars(obj) or obj.__dict__. You can then use the update method of the dict to add a set of names to your object.
eg.
class SomeClass:
def __str__(self):
return "SomeClass({})".format(
", ".join(
"{}={!r}".format(key, value)
for key, value in self.__dict__.items()
)
)
__repr__ = __str__
target_names = ['var_a', 'var_b', 'var_c']
target_values = [1, 2, 3]
target = dict(zip(target_names, target_values))
assert target == {'var_a': 1, 'var_b': 2, 'var_c': 3}
s = SomeClass()
vars(s).update(target)
assert hasattr(s, 'var_a')
assert s.var_a == 1
print(s) # prints SomeClass(var_c=3, var_a=1, var_b=2)

How to specify multiple author(s) / email(s) in setup.py

We wrote a small wrapper to a twitter app and published this information to http://pypi.python.org. But setup.py just contained a single field for specifying email / name of the author. How do I specify multiple contributors / email list, to the following fields since we would like this package to be listed under our names, much similar to how it shows up in http://rubygems.org.
author='foo',
author_email='foo.bar#gmail.com',
As far as I know, setuptools doesn't support using a list of strings in order to specify multiple authors. Your best bet is to list the authors in a single string:
author='Foo Bar, Spam Eggs',
author_email='foobar#baz.com, spameggs#joe.org',
I'm not sure if PyPI validates the author_email field, so you may run into trouble with that one. In any case, I would recommend you limit these to a single author and mention all contributors in the documentation or description.
Some sources:
This has been registered as a bug, actually, but it seems like support for multiple authors was not implemented. Here is an alternative solution. Here is an idea for how to provide a contact email for a project with multiple authors.
I'm sort of just piggybacking off of #modocache's answer, in case you want some specifics.
Throughout this answer, I'll be refering to a python3.6 version of the FOO-PYTHON-ENV\Lib\distutils\dist.py file
To reiterate, you cannot use a list in the author field. Here's why:
Spoiler: Two methods belonging to the DistributionMetadata class are the reason --
def _read_field(name):
value = msg[name]
if value == 'UNKNOWN':
return None
return value
def _read_list(name):
values = msg.get_all(name, None)
if values == []:
return None
return values
Here's where you'll hit an error if you try to stick a list in the author field:
class DistributionMetadata:
#*...(R E D A C T E D)...*#
def read_pkg_file(self, file):
"""Reads the metadata values from a file object."""
#*...(R E D A C T E D)...*#
# ####################################
# Note the usage of _read_field() here
# ####################################
self.name = _read_field('name')
self.version = _read_field('version')
self.description = _read_field('summary')
# we are filling author only.
self.author = _read_field('author')
self.maintainer = None
self.author_email = _read_field('author-email')
self.maintainer_email = None
self.url = _read_field('home-page')
self.license = _read_field('license')
#*...(R E D A C T E D)...*#
# ###################################
# Note the usage of _read_list() here
# ###################################
self.platforms = _read_list('platform')
self.classifiers = _read_list('classifier')
#*...(R E D A C T E D)...*#
& Here's the whole thing:
class DistributionMetadata:
"""Dummy class to hold the distribution meta-data: name, version,
author, and so forth.
"""
_METHOD_BASENAMES = ("name", "version", "author", "author_email",
"maintainer", "maintainer_email", "url",
"license", "description", "long_description",
"keywords", "platforms", "fullname", "contact",
"contact_email", "classifiers", "download_url",
# PEP 314
"provides", "requires", "obsoletes",
)
def __init__(self, path=None):
if path is not None:
self.read_pkg_file(open(path))
else:
self.name = None
self.version = None
self.author = None
self.author_email = None
self.maintainer = None
self.maintainer_email = None
self.url = None
self.license = None
self.description = None
self.long_description = None
self.keywords = None
self.platforms = None
self.classifiers = None
self.download_url = None
# PEP 314
self.provides = None
self.requires = None
self.obsoletes = None
def read_pkg_file(self, file):
"""Reads the metadata values from a file object."""
msg = message_from_file(file)
def _read_field(name):
value = msg[name]
if value == 'UNKNOWN':
return None
return value
def _read_list(name):
values = msg.get_all(name, None)
if values == []:
return None
return values
metadata_version = msg['metadata-version']
self.name = _read_field('name')
self.version = _read_field('version')
self.description = _read_field('summary')
# we are filling author only.
self.author = _read_field('author')
self.maintainer = None
self.author_email = _read_field('author-email')
self.maintainer_email = None
self.url = _read_field('home-page')
self.license = _read_field('license')
if 'download-url' in msg:
self.download_url = _read_field('download-url')
else:
self.download_url = None
self.long_description = _read_field('description')
self.description = _read_field('summary')
if 'keywords' in msg:
self.keywords = _read_field('keywords').split(',')
self.platforms = _read_list('platform')
self.classifiers = _read_list('classifier')
# PEP 314 - these fields only exist in 1.1
if metadata_version == '1.1':
self.requires = _read_list('requires')
self.provides = _read_list('provides')
self.obsoletes = _read_list('obsoletes')
else:
self.requires = None
self.provides = None
self.obsoletes = None
Consider using flit to build the package, as this build system supports multiple authors and maintainers. Store this metadata in pyproject.toml as follows:
[build-system]
requires = ["flit_core >=3.2,<4"]
build-backend = "flit_core.buildapi"
[project]
...
authors = [
{name = "First1 Last1", email = "name1#foo.bar"},
{name = "First2 Last2", email = "name2#foo.bar"},
]
maintainers = [
{name = "First1 Last1", email = "name1#foo.bar"},
{name = "First2 Last2", email = "name2#foo.bar"},
]

Categories

Resources