コード例 #1
0
ファイル: guidelines.py プロジェクト: chintal/tendril
 def _load_guidelines(self):
     with open(self._guidelinefile, 'r') as f:
         data = yaml.load(f)
         self._idents = data['idents']
         self._generators = data['generators']
         self._devices = data['devices']
         self._default = data['default']
コード例 #2
0
ファイル: configbase.py プロジェクト: chintal/tendril
 def get_configs_file(self):
     with open(self._cfpath) as configfile:
         configdata = yaml.load(configfile)
         try:
             return self._verify_schema_decl(configdata)
         except SchemaNotSupportedError as e:
             self._validation_errors.add(e)
コード例 #3
0
ファイル: guidelines.py プロジェクト: chintal/tendril
 def _load_guidelines(self):
     with open(self._guidelinefile, 'r') as f:
         data = yaml.load(f)
         self._idents = data['idents']
         self._generators = data['generators']
         self._devices = data['devices']
         self._default = data['default']
コード例 #4
0
ファイル: order.py プロジェクト: chintal/tendril
    def create(self, title=None, desc=None, cards=None, deltas=None,
               sourcing_order_snos=None, root_order_snos=None,
               ordered_by=None, order_yaml_path=None, snomap_path=None,
               force=False):
        # Load in the various parameters and such, creating the necessary
        # containers only.
        self._force = force
        if self._defined is True and self._force is False:
            raise Exception("This production order instance seems to be "
                            "already defined. You can't 'create' it again.")
        if order_yaml_path is not None:
            self._order_yaml_path = order_yaml_path
            with open(self._order_yaml_path, 'r') as f:
                self._yaml_data = yaml.load(f)
            self._load_order_yaml_data()
        if title:
            self._title = title
        if desc:
            self._desc = desc
        if cards:
            self._cards = cards
        if deltas:
            self._deltas = deltas
        if sourcing_order_snos:
            self._sourcing_order_snos = sourcing_order_snos
        if root_order_snos:
            self._root_order_snos = root_order_snos
        if ordered_by:
            self._ordered_by = ordered_by
        if snomap_path:
            self._snomap_path = snomap_path

        if len(self._cards) + len(self._deltas) == 0:
            raise NothingToProduceError
コード例 #5
0
ファイル: gedaproject.py プロジェクト: chintal/tendril
def get_pcbpricing_data(projfolder):
    pcbpricingfp = os.path.join(projfolder, 'pcb', 'sourcing.yaml')
    if not os.path.exists(pcbpricingfp):
        return None
    with open(pcbpricingfp, 'r') as f:
        data = yaml.load(f)
    return data
コード例 #6
0
ファイル: csil.py プロジェクト: chintal/tendril
 def _load_descriptors(self):
     gpf = projfile.GedaProjectFile(self._projectfolder)
     pricingfp = os.path.join(gpf.configsfile.projectfolder,
                              'pcb', 'sourcing.yaml')
     if not os.path.exists(pricingfp):
         logger.debug(
             "PCB does not have sourcing file. Not loading prices : " +
             self._pcbname
         )
         return None
     with open(pricingfp, 'r') as f:
         data = yaml.load(f)
     self._descriptors.append(str(data['params']['dX']) + 'mm x ' + str(data['params']['dY']) + 'mm')  # noqa
     if data["params"]["layers"] == 2:
         self._descriptors.append("Double Layer")
     elif data["params"]["layers"] == 4:
         self._descriptors.append("ML4")
     # HAL, Sn, Au, PBFREE, H, NP, I, OC
     if data["params"]["finish"] == 'Au':
         self._descriptors.append("Immersion Gold/ENIG finish")
     elif data["params"]["finish"] == 'Sn':
         self._descriptors.append("Immersion Tin finish")
     elif data["params"]["finish"] == 'PBFREE':
         self._descriptors.append("Any Lead Free finish")
     elif data["params"]["finish"] == 'H':
         self._descriptors.append("Lead F ree HAL finish")
     elif data["params"]["finish"] == 'NP':
         self._descriptors.append("No Copper finish")
     elif data["params"]["finish"] == 'I':
         self._descriptors.append("OSP finish")
     elif data["params"]["finish"] == 'OC':
         self._descriptors.append("Only Copper finish")
     else:
         self._descriptors.append("UNKNOWN FINISH: " + data["params"]["finish"])  # noqa
     self._descriptors.append("10 Working Days")
コード例 #7
0
ファイル: order.py プロジェクト: SayCV/tendril
 def _load_snomap_legacy(self):
     # New form should construct directly from DB
     snomap_path = docstore.get_docs_list_for_sno_doctype(
         serialno=self._sno, doctype='SNO MAP', one=True).path
     with docstore.docstore_fs.open(snomap_path, 'r') as f:
         snomap_data = yaml.load(f)
     self._snomap = SerialNumberMap(snomap_data, self._sno)
コード例 #8
0
def get_pcbpricing_data(projfolder):
    pcbpricingfp = os.path.join(projfolder, 'pcb', 'sourcing.yaml')
    if not os.path.exists(pcbpricingfp):
        return None
    with open(pcbpricingfp, 'r') as f:
        data = yaml.load(f)
    return data
コード例 #9
0
ファイル: order.py プロジェクト: chintal/tendril
    def create(self, title=None, desc=None, cards=None, deltas=None,
               sourcing_order_snos=None, root_order_snos=None,
               ordered_by=None, order_yaml_path=None, snomap_path=None,
               force=False):
        # Load in the various parameters and such, creating the necessary
        # containers only.
        self._force = force
        if self._defined is True and self._force is False:
            raise Exception("This production order instance seems to be already "
                            "done. You can't 'create' it again.")
        if order_yaml_path is not None:
            self._order_yaml_path = order_yaml_path
            with open(self._order_yaml_path, 'r') as f:
                self._yaml_data = yaml.load(f)
            self._load_order_yaml_data()
        if title:
            self._title = title
        if desc:
            self._desc = desc
        if cards:
            self._cards = cards
        if deltas:
            self._deltas = deltas
        if sourcing_order_snos:
            self._sourcing_order_snos = sourcing_order_snos
        if root_order_snos:
            self._root_order_snos = root_order_snos
        if ordered_by:
            self._ordered_by = ordered_by
        if snomap_path:
            self._snomap_path = snomap_path

        if len(self._cards) + len(self._deltas) == 0:
            raise NothingToProduceError
コード例 #10
0
ファイル: order.py プロジェクト: chintal/tendril
 def _load_snomap_legacy(self):
     # New form should construct directly from DB
     snomap_path = docstore.get_docs_list_for_sno_doctype(
         serialno=self._sno, doctype='SNO MAP', one=True
     ).path
     with docstore.docstore_fs.open(snomap_path, 'r') as f:
         snomap_data = yaml.load(f)
     self._snomap = SerialNumberMap(snomap_data, self._sno)
コード例 #11
0
ファイル: order.py プロジェクト: chintal/tendril
 def _load_order_yaml(self):
     try:
         order_path = docstore.get_docs_list_for_sno_doctype(
             serialno=self._sno, doctype='PRODUCTION ORDER YAML', one=True
         ).path
     except SerialNoNotFound:
         raise ProductionOrderNotFound
     with docstore.docstore_fs.open(order_path, 'r') as f:
         self._yaml_data = yaml.load(f)
コード例 #12
0
ファイル: order.py プロジェクト: chintal/tendril
 def _load_order_yaml(self):
     try:
         order_path = docstore.get_docs_list_for_sno_doctype(
             serialno=self._sno, doctype='PRODUCTION ORDER YAML', one=True
         ).path
     except SerialNoNotFound:
         raise ProductionOrderNotFound
     with docstore.docstore_fs.open(order_path, 'r') as f:
         self._yaml_data = yaml.load(f)
コード例 #13
0
 def _load_external_sources(self):
     external_configs = yml.load(self._path)
     for config in external_configs:
         try:
             if config['format'] == 'json':
                 self._sources.append(
                     ConfigExternalJSONSource(config['path'],
                                              config['keymap']))
             else:
                 raise ExternalConfigFormatError(config['path'],
                                                 config['filetype'])
         except ExternalConfigMissingError:
             pass
コード例 #14
0
ファイル: customs.py プロジェクト: chintal/tendril
    def __init__(self, vendor, inv_yaml, working_folder=None):
        vendor_defaults_file = os.path.join(CUSTOMSDEFAULTS_FOLDER,
                                            vendor._name + '.yaml')
        self._data = {}
        if os.path.exists(vendor_defaults_file):
            with open(vendor_defaults_file, 'r') as f:
                vendor_defaults = yaml.load(f)
                self._data = vendor_defaults.copy()
        else:
            logger.warning("Vendor Customs Defaults File Not Found : " +
                           vendor_defaults_file)
        self._source_folder = os.path.split(inv_yaml)[0]
        if working_folder is None:
            self._working_folder = self._source_folder
        else:
            self._working_folder = working_folder
        with open(inv_yaml, 'r') as f:
            inv_data = yaml.load(f)
            self._data.update(inv_data)
        self._linetype = CustomsInvoiceLine
        vendor.currency = currency.CurrencyDefinition(
            vendor.currency.code, vendor.currency.symbol,
            exchval=self._data['exchrate']
        )
        super(CustomsInvoice, self).__init__(
            vendor, self._data['invoice_no'], self._data['invoice_date']
        )

        self.freight = 0
        self.insurance_pc = 0
        self._includes_freight = False
        self._added_insurance = False
        self._process_other_costs()
        hs_codes_file = os.path.join(CUSTOMSDEFAULTS_FOLDER, 'hs_codes.yaml')
        with open(hs_codes_file, 'r') as f:
            self._hs_codes = yaml.load(f)
        self._sections = []
コード例 #15
0
    def __init__(self, vendor, inv_yaml, working_folder=None):
        vendor_defaults_file = os.path.join(CUSTOMSDEFAULTS_FOLDER,
                                            vendor._name + '.yaml')
        self._data = {}
        if os.path.exists(vendor_defaults_file):
            with open(vendor_defaults_file, 'r') as f:
                vendor_defaults = yaml.load(f)
                self._data = vendor_defaults.copy()
        else:
            logger.warning("Vendor Customs Defaults File Not Found : " +
                           vendor_defaults_file)
        self._source_folder = os.path.split(inv_yaml)[0]
        if working_folder is None:
            self._working_folder = self._source_folder
        else:
            self._working_folder = working_folder
        with open(inv_yaml, 'r') as f:
            inv_data = yaml.load(f)
            self._data.update(inv_data)
        self._linetype = CustomsInvoiceLine
        vendor.currency = currency.CurrencyDefinition(
            vendor.currency.code,
            vendor.currency.symbol,
            exchval=self._data['exchrate'])
        super(CustomsInvoice, self).__init__(vendor, self._data['invoice_no'],
                                             self._data['invoice_date'])

        self.freight = 0
        self.insurance_pc = 0
        self._includes_freight = False
        self._added_insurance = False
        self._process_other_costs()
        hs_codes_file = os.path.join(CUSTOMSDEFAULTS_FOLDER, 'hs_codes.yaml')
        with open(hs_codes_file, 'r') as f:
            self._hs_codes = yaml.load(f)
        self._sections = []
コード例 #16
0
ファイル: pricelist.py プロジェクト: chintal/tendril
 def __init__(self, name, dname, pclass, mappath=None,
              currency_code=None, currency_symbol=None,
              pricelistpath=None, **kwargs):
     if pricelistpath is None:
         pricelistpath = os.path.join(PRICELISTVENDORS_FOLDER,
                                      name + '-pricelist.yaml')
     with open(pricelistpath, 'r') as f:
         self._pricelist = yaml.load(f)
     self._last_updated = get_file_mtime(pricelistpath)
     if currency_code is None:
         currency_code = self._pricelist["currency"]["code"].strip()
     if currency_symbol is None:
         currency_symbol = self._pricelist["currency"]["symbol"].strip()
     self._currency = currency.CurrencyDefinition(
         currency_code, currency_symbol
     )
     super(VendorPricelist, self).__init__(name, dname, pclass, mappath,
                                           currency_code, currency_symbol,
                                           **kwargs)
     if 'vendorinfo' in self._pricelist:
         if "effectivefactor" in self._pricelist["vendorinfo"]:
             self.add_order_additional_cost_component(
                 "Unspecified",
                 self._pricelist["vendorinfo"]["effectivefactor"] * 100
             )
     self._vpart_class = PricelistPart
     try:
         self.add_order_baseprice_component(
             "Shipping Cost",
             self._pricelist["vendorinfo"]["shippingcost"]
         )
     except KeyError:
         pass
     if "prices" not in self._pricelist:
         try:
             pass
         except:
             logger.error("No prices found for " + self.name)
     if "pricegens" in self._pricelist:
         self._generate_insert_idents()
     if "pricecsv" in self._pricelist:
         self._load_pricecsv(self._pricelist["pricecsv"])
コード例 #17
0
 def _load_prices(self):
     gpf = projfile.GedaProjectFile(self._projectfolder)
     pricingfp = os.path.join(gpf.configsfile.projectfolder, 'pcb',
                              'sourcing.yaml')
     if not os.path.exists(pricingfp):
         logger.debug(
             "PCB does not have sourcing file. Not loading prices : " +
             self._pcbname)
         return None
     with open(pricingfp, 'r') as f:
         data = yaml.load(f)
     for qty, prices in viewitems(data['pricing']):
         if 10 not in prices.keys():
             logger.warning(
                 "Default Delivery Time not in prices. Quantity pricing not imported : "
                 +  # noqa
                 str([qty, self._pcbname]))
         else:
             price = VendorPrice(qty, prices[10], self._vendor.currency)
             self._prices.append(price)
コード例 #18
0
ファイル: products.py プロジェクト: SayCV/tendril
 def _load_product_info(self):
     with open(self._fpath, 'r') as f:
         self._raw_data = yaml.load(f)
     self._name = self._raw_data['name']
     self._card_names = self._raw_data['cards']
     self._cable_names = self._raw_data['cables']
     self._labels = self._raw_data['labels']
     # TODO Some products don't have a viable core. Allowances must be made
     # Eg QM anf QI.
     self._core = self._raw_data['derive_sno_from']
     self._calibformat = self._raw_data['calibformat']
     try:
         self._product_info = \
             INSTANCE_PRODUCT_CLASSES.get_product_info_class(
                 self._raw_data['productinfo']['line'],
                 infodict=self._raw_data['productinfo'], parent=self
             )
     except ImportError:
         self._product_info = ProductInfo(
             infodict=self._raw_data['productinfo'], parent=self)
コード例 #19
0
ファイル: pricelist.py プロジェクト: SayCV/tendril
 def __init__(self,
              name,
              dname,
              pclass,
              mappath=None,
              currency_code=None,
              currency_symbol=None,
              pricelistpath=None,
              **kwargs):
     if pricelistpath is None:
         pricelistpath = os.path.join(PRICELISTVENDORS_FOLDER,
                                      name + '-pricelist.yaml')
     with open(pricelistpath, 'r') as f:
         self._pricelist = yaml.load(f)
     self._last_updated = get_file_mtime(pricelistpath)
     if currency_code is None:
         currency_code = self._pricelist["currency"]["code"].strip()
     if currency_symbol is None:
         currency_symbol = self._pricelist["currency"]["symbol"].strip()
     self._currency = currency.CurrencyDefinition(currency_code,
                                                  currency_symbol)
     super(VendorPricelist,
           self).__init__(name, dname, pclass, mappath, currency_code,
                          currency_symbol, **kwargs)
     if 'vendorinfo' in self._pricelist:
         if "effectivefactor" in self._pricelist["vendorinfo"]:
             self.add_order_additional_cost_component(
                 "Unspecified",
                 self._pricelist["vendorinfo"]["effectivefactor"] * 100)
     self._vpart_class = PricelistPart
     try:
         self.add_order_baseprice_component(
             "Shipping Cost", self._pricelist["vendorinfo"]["shippingcost"])
     except KeyError:
         pass
     if "prices" not in self._pricelist:
         logger.error("No prices found for " + self.name)
     if "pricegens" in self._pricelist:
         self._generate_insert_idents()
     if "pricecsv" in self._pricelist:
         self._load_pricecsv(self._pricelist["pricecsv"])
コード例 #20
0
ファイル: customs.py プロジェクト: SayCV/tendril
def get_customs_invoice(serialno):
    documents = docstore.controller.get_sno_documents(serialno=serialno)
    inv_yaml = None
    for document in documents:
        if document.doctype == 'INVOICE-DATA-YAML':
            inv_yaml = document.docpath
    if not inv_yaml:
        raise ValueError('Invoice data not found for : ' + serialno)
    with docstore.docstore_fs.open(inv_yaml, 'r') as f:
        inv_data = yaml.load(f)

    inv_format = inv_data['invoice_format']

    if inv_format == 'analogdevices':
        from tendril.sourcing import pricelist
        invoice_class = pricelist.AnalogDevicesInvoice
    elif inv_format == 'digikey':
        from tendril.sourcing.vendors import digikey
        invoice_class = digikey.DigiKeyInvoice
    else:
        raise ValueError('Unrecognized Customs Invoice Format : ' +
                         inv_format)

    from tendril.sourcing import electronics
    vobj = electronics.get_vendor_by_name(inv_format)

    workspace_name = get_tempname()
    docstore.copy_docs_to_workspace(serialno=serialno,
                                    workspace=workspace_name,
                                    clearws=True,
                                    fs=temp_fs)

    invoice = invoice_class(
        vobj,
        temp_fs.getsyspath(
            fs.path.join(workspace_name, 'inv_data.yaml')
        )
    )

    temp_fs.removedir(workspace_name, recursive=True, force=True)
    return invoice
コード例 #21
0
ファイル: customs.py プロジェクト: chintal/tendril
def get_customs_invoice(serialno):
    documents = docstore.controller.get_sno_documents(serialno=serialno)
    inv_yaml = None
    for document in documents:
        if document.doctype == 'INVOICE-DATA-YAML':
            inv_yaml = document.docpath
    if not inv_yaml:
        raise ValueError('Invoice data not found for : ' + serialno)
    with docstore.docstore_fs.open(inv_yaml, 'r') as f:
        inv_data = yaml.load(f)

    inv_format = inv_data['invoice_format']

    if inv_format == 'analogdevices':
        from tendril.sourcing import pricelist
        invoice_class = pricelist.AnalogDevicesInvoice
    elif inv_format == 'digikey':
        from tendril.sourcing import digikey
        invoice_class = digikey.DigiKeyInvoice
    else:
        raise ValueError('Unrecognized Customs Invoice Format : ' +
                         inv_format)

    from tendril.sourcing import electronics
    vobj = electronics.get_vendor_by_name(inv_format)

    workspace_name = get_tempname()
    docstore.copy_docs_to_workspace(serialno=serialno,
                                    workspace=workspace_name,
                                    clearws=True,
                                    fs=temp_fs)

    invoice = invoice_class(
        vobj,
        temp_fs.getsyspath(
            fs.path.join(workspace_name, 'inv_data.yaml')
        )
    )

    temp_fs.removedir(workspace_name, recursive=True, force=True)
    return invoice
コード例 #22
0
ファイル: products.py プロジェクト: chintal/tendril
 def _load_product_info(self):
     with open(self._fpath, 'r') as f:
         self._raw_data = yaml.load(f)
     self._name = self._raw_data['name']
     self._card_names = self._raw_data['cards']
     self._cable_names = self._raw_data['cables']
     self._labels = self._raw_data['labels']
     # TODO Some products don't have a viable core. Allowances must be made
     # Eg QM anf QI.
     self._core = self._raw_data['derive_sno_from']
     self._calibformat = self._raw_data['calibformat']
     try:
         self._product_info = \
             INSTANCE_PRODUCT_CLASSES.get_product_info_class(
                 self._raw_data['productinfo']['line'],
                 infodict=self._raw_data['productinfo'], parent=self
             )
     except ImportError:
         self._product_info = ProductInfo(
             infodict=self._raw_data['productinfo'], parent=self
         )
コード例 #23
0
ファイル: csil.py プロジェクト: chintal/tendril
 def _load_prices(self):
     gpf = projfile.GedaProjectFile(self._projectfolder)
     pricingfp = os.path.join(gpf.configsfile.projectfolder,
                              'pcb', 'sourcing.yaml')
     if not os.path.exists(pricingfp):
         logger.debug(
             "PCB does not have sourcing file. Not loading prices : " +
             self._pcbname
         )
         return None
     with open(pricingfp, 'r') as f:
         data = yaml.load(f)
     for qty, prices in viewitems(data['pricing']):
         if 10 not in prices.keys():
             logger.warning(
                 "Default Delivery Time not in prices. Quantity pricing not imported : " +  # noqa
                 str([qty, self._pcbname])
             )
         else:
             price = VendorPrice(
                 qty, prices[10], self._vendor.currency
             )
             self._prices.append(price)
コード例 #24
0
 def _load_descriptors(self):
     gpf = projfile.GedaProjectFile(self._projectfolder)
     pricingfp = os.path.join(gpf.configsfile.projectfolder, 'pcb',
                              'sourcing.yaml')
     if not os.path.exists(pricingfp):
         logger.debug(
             "PCB does not have sourcing file. Not loading prices : " +
             self._pcbname)
         return None
     with open(pricingfp, 'r') as f:
         data = yaml.load(f)
     self._descriptors.append(
         str(data['params']['dX']) + 'mm x ' + str(data['params']['dY']) +
         'mm')  # noqa
     if data["params"]["layers"] == 2:
         self._descriptors.append("Double Layer")
     elif data["params"]["layers"] == 4:
         self._descriptors.append("ML4")
     # HAL, Sn, Au, PBFREE, H, NP, I, OC
     if data["params"]["finish"] == 'Au':
         self._descriptors.append("Immersion Gold/ENIG finish")
     elif data["params"]["finish"] == 'Sn':
         self._descriptors.append("Immersion Tin finish")
     elif data["params"]["finish"] == 'PBFREE':
         self._descriptors.append("Any Lead Free finish")
     elif data["params"]["finish"] == 'H':
         self._descriptors.append("Lead F ree HAL finish")
     elif data["params"]["finish"] == 'NP':
         self._descriptors.append("No Copper finish")
     elif data["params"]["finish"] == 'I':
         self._descriptors.append("OSP finish")
     elif data["params"]["finish"] == 'OC':
         self._descriptors.append("Only Copper finish")
     else:
         self._descriptors.append("UNKNOWN FINISH: " +
                                  data["params"]["finish"])  # noqa
     self._descriptors.append("10 Working Days")
コード例 #25
0
from tendril.utils.config import INSTANCE_ROOT
from tendril.utils.files import yml as yaml

from tendril.utils import log

logger = log.get_logger(__name__, log.DEFAULT)

if __name__ == '__main__':

    bomlist = []

    orderfolder = os.path.join(INSTANCE_ROOT, 'scratch', 'sourcing', 'current')
    orderfile = os.path.join(orderfolder, 'order.yaml')

    with open(orderfile, 'r') as f:
        data = yaml.load(f)

    LOAD_PRESHORT = False
    LOAD_EXTERNAL_REQ = False
    EXTERNAL_REQ_IMMEDIATE = True
    external_req_file = None
    USE_STOCK = True
    IS_INDICATIVE = False
    indication_context = None
    PRIORITIZE = False
    PRELIMINARY = False
    IMMEDIATE_EARMARKS = []

    if 'preshort' in data.keys():
        LOAD_PRESHORT = data['preshort']
    if 'use_stock' in data.keys():
コード例 #26
0
 def _get_yaml_file(self):
     if self.template and not os.path.exists(self._path):
         self._generate_stub()
     if self.FileNotFoundExceptionType and not os.path.exists(self._path):
         raise self.FileNotFoundExceptionType(self._path)
     return yaml.load(self._path)
コード例 #27
0
ファイル: order.py プロジェクト: chintal/tendril
from tendril.utils.config import INSTANCE_ROOT
from tendril.utils.files import yml as yaml

from tendril.utils import log
logger = log.get_logger(__name__, log.DEFAULT)

if __name__ == '__main__':

    bomlist = []

    orderfolder = os.path.join(INSTANCE_ROOT, 'scratch',
                               'sourcing', 'current')
    orderfile = os.path.join(orderfolder, 'order.yaml')

    with open(orderfile, 'r') as f:
        data = yaml.load(f)

    LOAD_PRESHORT = False
    LOAD_EXTERNAL_REQ = False
    EXTERNAL_REQ_IMMEDIATE = True
    external_req_file = None
    USE_STOCK = True
    IS_INDICATIVE = False
    indication_context = None
    PRIORITIZE = False
    PRELIMINARY = False
    IMMEDIATE_EARMARKS = []

    if 'preshort' in data.keys():
        LOAD_PRESHORT = data['preshort']
    if 'use_stock' in data.keys():
コード例 #28
0
 def _load_sections(self):
     hs_codes_file = os.path.join(CUSTOMSDEFAULTS_FOLDER, 'hs_codes.yaml')
     with open(hs_codes_file, 'r') as f:
         data = yaml.load(f)
         for section, sectiondict in data['sections'].iteritems():
             self._sections.append(CustomsSection(section, sectiondict))
コード例 #29
0
ファイル: order.py プロジェクト: chintal/tendril
    def _process(self, outfolder=None, manifestsfolder=None,
                 label_manager=None, register=False, force=False,
                 pb_class=None, stacked_pb=False, leaf_pb=True,
                 session=None):
        self._force = force

        if pb_class is None:
            pb_class = TendrilProgressBar

        if stacked_pb is True:
            pb = pb_class(max=8)
        else:
            pb = DummyProgressBar(max=8)

        pb.next(note="Constructing Resources for Production Order Generation")

        if outfolder is None:
            if self._order_yaml_path is not None:
                outfolder = os.path.split(self._order_yaml_path)[0]
            else:
                raise AttributeError('Output folder needs to be defined')

        if manifestsfolder is None:
            manifestsfolder = os.path.join(outfolder, 'manifests')
            if not os.path.exists(manifestsfolder):
                os.makedirs(manifestsfolder)

        if self._sno is None:
            self._sno = serialnos.get_serialno(
                    series='PROD', efield=self._title,
                    register=register, session=session
            )

        # Create Snomap
        if self._snomap_path is not None:
            with open(self._snomap_path, 'r') as f:
                self._snomap = SerialNumberMap(yaml.load(f), self._sno)
        else:
            self._snomap = SerialNumberMap({}, self._sno)

        self._snomap.set_session(session=session)
        if register is True:
            self._snomap.enable_creation()

        indent_sno = self._snomap.get_sno('indentsno')
        if register is True:
            serialnos.link_serialno(child=indent_sno, parent=self.serialno,
                                    verbose=False, session=session)

        # Create cards and deltas and so forth
        pb.next(note="Constructing Production Order Actions")
        actions = self.card_actions + self.delta_actions

        pb.next(note="Executing Production Order Actions")
        for action in actions:
            if register is False:
                action.scaffold = True
            action.set_session(session=session)
            action.commit(
                outfolder=manifestsfolder, indent_sno=indent_sno,
                prod_ord_sno=self._sno, register=register, session=session,
                pb_class=pb_class, stacked_pb=stacked_pb, leaf_pb=leaf_pb,
            )

        self._snomap.disable_creation()

        pb.next(note="Constructing Composite Output BOM")
        cobom = CompositeOutputBom(self.bomlist)

        pb.next(note="Creating Indent(s)")
        self._process_indents(
            indent_sno=indent_sno, cobom=cobom, outfolder=outfolder,
            register=register, force=force, session=session
        )

        pb.next(note="Generating Production Order Document")
        # Make production order doc
        self._last_generated_at = arrow.utcnow().isoformat()
        if self._first_generated_at is None:
            self._first_generated_at = arrow.utcnow().isoformat()
        self._dump_order_yaml(outfolder=outfolder, register=register,
                              session=session)
        self._generate_doc(outfolder=outfolder, register=register,
                           session=session)

        pb.next(note="Generating Labels")
        self.make_labels(label_manager=label_manager, pb_class=pb_class,
                         stacked_pb=stacked_pb, leaf_pb=leaf_pb)

        pb.next(note="Finalizing Production Order")
        for action in actions:
            action.scaffold = False
            action.unset_session()
        self._snomap.dump_to_file(outfolder)
        self._snomap.unset_session()

        if register is True:
            docstore.register_document(
                    serialno=self.serialno,
                    docpath=os.path.join(outfolder, 'snomap.yaml'),
                    doctype='SNO MAP', efield=self.title,
                    verbose=False, session=session
            )
        pb.finish()
        self._defined = True
コード例 #30
0
ファイル: gsymlib.py プロジェクト: chintal/tendril
    def _get_data(self):
        with open(self._genpath) as genfile:
            gendata = yaml.load(genfile)
        if gendata["schema"]["name"] == "gsymgenerator" and gendata["schema"]["version"] == 1.0:

            if gendata["type"] == "simple":
                self._type = "Simple"
                self._ivalues = [v for v in gendata["values"] if v is not None and v.strip() is not None]
                return gendata["values"]
            values = []

            if gendata["type"] == "resistor":
                self._type = "Resistor"
                for resistance in gendata["resistances"]:
                    if resistance is not None:
                        values.append(resistance)
                        self._iunits.append(resistance)
                if "generators" in gendata.keys():
                    for generator in gendata["generators"]:
                        self._igen.append(generator)
                        if generator["std"] == "iec60063":
                            rvalues = iec60063.gen_vals(
                                generator["series"], iec60063.res_ostrs, start=generator["start"], end=generator["end"]
                            )
                            for rvalue in rvalues:
                                values.append(construct_resistor(rvalue, generator["wattage"]))  # noqa
                        else:
                            raise ValueError
                if "values" in gendata.keys():
                    if gendata["values"][0].strip() != "":
                        values += gendata["values"]
                        self._ivalues.extend(gendata["values"])
                if "custom_series" in gendata.keys():
                    from tendril.conventions.series import CustomValueSeries

                    for name, series in viewitems(gendata["custom_series"]):
                        if series["detail"].pop("type") != "resistor":
                            raise ValueError("Expected a resistor series")
                        vals = series["values"]
                        tsymbol = GedaSymbol(self._sympath)
                        iseries = CustomValueSeries(
                            name, "resistor", device=tsymbol.device, footprint=tsymbol.footprint
                        )
                        for type_val, val in viewitems(vals):
                            iseries.add_value(type_val, val)
                        iseries._desc = series["detail"].pop("desc")
                        iseries._aparams = series["detail"]
                        self._iseries.append(iseries)
                        values.extend(vals.values())
                return values

            if gendata["type"] == "capacitor":
                self._type = "Capacitor"
                for capacitance in gendata["capacitances"]:
                    if capacitance is not None:
                        values.append(capacitance)
                        self._iunits.append(capacitance)
                if "generators" in gendata.keys():
                    for generator in gendata["generators"]:
                        self._igen.append(generator)
                        if generator["std"] == "iec60063":
                            cvalues = iec60063.gen_vals(
                                generator["series"], iec60063.cap_ostrs, start=generator["start"], end=generator["end"]
                            )
                            for cvalue in cvalues:
                                values.append(construct_capacitor(cvalue, generator["voltage"]))  # noqa
                        else:
                            raise ValueError
                if "values" in gendata.keys():
                    if gendata["values"][0].strip() != "":
                        values += gendata["values"]
                        self._ivalues.append(gendata["values"])
                if "custom_series" in gendata.keys():
                    from tendril.conventions.series import CustomValueSeries

                    for name, series in viewitems(gendata["custom_series"]):
                        if series["detail"].pop("type") != "resistor":
                            raise ValueError("Expected a resistor series")
                        vals = series["values"]
                        tsymbol = GedaSymbol(self._sympath)
                        iseries = CustomValueSeries(
                            name, "resistor", device=tsymbol.device, footprint=tsymbol.footprint
                        )
                        for type_val, val in viewitems(vals):
                            iseries.add_value(type_val, val)
                        iseries._desc = series["detail"].pop("desc")
                        iseries._aparams = series["detail"]
                        self._iseries.append(iseries)
                        values.extend(vals.values())
                return values
            elif gendata["type"] == "wire":
                for gauge in gendata["gauges"]:
                    for color in gendata["colors"]:
                        values.append("{0} {1}".format(gauge, color))
                return values
        else:
            logger.ERROR("Config file schema is not supported")
コード例 #31
0
ファイル: customs.py プロジェクト: chintal/tendril
 def _load_sections(self):
     hs_codes_file = os.path.join(CUSTOMSDEFAULTS_FOLDER, 'hs_codes.yaml')
     with open(hs_codes_file, 'r') as f:
         data = yaml.load(f)
         for section, sectiondict in data['sections'].iteritems():
             self._sections.append(CustomsSection(section, sectiondict))
コード例 #32
0
ファイル: configbase.py プロジェクト: SayCV/tendril
 def get_configs_file(self):
     configdata = yaml.load(self._cfpath)
     try:
         return self._verify_schema_decl(configdata)
     except SchemaNotSupportedError as e:
         self._validation_errors.add(e)
コード例 #33
0
def gen_pcbpricing(projfolder, namebase, force=False):
    """
    Generates a PDF file with the pricing of the (bare) PCB provided by the
    gEDA project.

    The pcb file is the one listed in the gEDA project file, and the
    pcbname is the one specified in the
    :mod:`tendril.gedaif.conffile.ConfigsFile`. The pricing information is
    read out from the PCB's ``sourcing.yaml`` file, which in turn is intended
    to be created by sourcing modules.

    .. todo:: This function presently uses
              :func:`tendril.dox.render.render_lineplot`, which is marked for
              deprecation. It should be rewritten to use the
              :func:`tendril.dox.render.make_graph` route instead.

    :param projfolder: The gEDA project folder.
    :type projfolder: str
    :param namebase: The project name.
    :type namebase: str
    :param force: Regenerate even if up-to-date.
    :type force: bool
    :return: The output file path.

    .. rubric:: Paths

    * Output File :  ``<project_doc_folder>/<namebase>-pricing.pdf``
    * Source Files : ``<projectfolder>/pcb/sourcing.yaml``

    """
    gpf = projfile.GedaProjectFile(projfolder)
    pcbpricingfp = os.path.join(gpf.configsfile.projectfolder, 'pcb',
                                'sourcing.yaml')
    pcbpricing_mtime = fsutils.get_file_mtime(pcbpricingfp)

    if not os.path.exists(pcbpricingfp):
        return None

    docfolder = get_project_doc_folder(projfolder)
    plotfile = path.join(docfolder, namebase + '-pricing.pdf')
    outf_mtime = fsutils.get_file_mtime(plotfile, fs=refdoc_fs)

    if not force and outf_mtime is not None and outf_mtime > pcbpricing_mtime:
        logger.debug('Skipping up-to-date ' + pcbpricingfp)
        return pcbpricingfp

    logger.info('Regnerating ' + plotfile + os.linesep + 'Last modified : ' +
                str(pcbpricing_mtime) + '; Last Created : ' + str(outf_mtime))

    with open(pcbpricingfp, 'r') as f:
        data = yaml.load(f)

    workspace_outpath = workspace_fs.getsyspath(plotfile)
    workspace_folder = workspace_fs.getsyspath(path.dirname(plotfile))
    workspace_fs.makedir(path.dirname(plotfile),
                         recursive=True,
                         allow_recreate=True)

    plot1file = os.path.join(workspace_folder, namebase + '-1pricing.pdf')
    plot2file = os.path.join(workspace_folder, namebase + '-2pricing.pdf')

    pltnote = "This pricing refers to the bare PCB only. " \
              "See the corresponding Config Docs for Card Pricing"

    plt1data = {
        key: data['pricing'][key]
        for key in data['pricing'].keys() if key <= 10
    }
    plt1title = gpf.configsfile.configdata['pcbname']
    plt1title += " PCB Unit Price vs Order Quantity (Low Quantity)"
    plot1file = render.render_lineplot(plot1file, plt1data, plt1title, pltnote)

    if max(data['pricing'].keys()) > 10:
        plt2data = {
            key: data['pricing'][key]
            for key in data['pricing'].keys() if key > 10
        }
        plt2title = gpf.configsfile.configdata['pcbname']
        plt2title += " PCB Unit Price vs Order Quantity (Production Quantity)"
        plot2file = render.render_lineplot(plot2file, plt2data, plt2title,
                                           pltnote)
        pdf.merge_pdf([plot1file, plot2file], workspace_outpath)
        os.remove(plot2file)
    else:
        shutil.copyfile(plot1file, workspace_outpath)
    os.remove(plot1file)
    copyfile(workspace_fs, plotfile, refdoc_fs, plotfile, overwrite=True)
    return plotfile
コード例 #34
0
ファイル: gsymlib.py プロジェクト: SayCV/tendril
    def _get_data(self):
        with open(self._genpath) as genfile:
            gendata = yaml.load(genfile)
        if gendata["schema"]["name"] == "gsymgenerator" and \
           gendata["schema"]["version"] == 1.0:

            if gendata['type'] == 'simple':
                self._type = 'Simple'
                self._ivalues = [
                    v for v in gendata['values']
                    if v is not None and v.strip() is not None
                ]
                return gendata['values']
            values = []

            if gendata['type'] == 'resistor':
                self._type = 'Resistor'
                giseries = None
                for resistance in gendata['resistances']:
                    if resistance is not None:
                        values.append(resistance)
                        self._iunits.append(resistance)
                if 'composite_series' in gendata.keys():
                    from tendril.conventions.series import CustomValueSeries
                    try:
                        name = gendata['composite_series']['name']
                        tsymbol = GedaSymbol(self._sympath)
                        giseries = CustomValueSeries(
                            name,
                            'resistor',
                            device=tsymbol.device,
                            footprint=tsymbol.footprint)
                    except KeyError:
                        pass
                if 'generators' in gendata.keys():
                    dcomponents = jb_resistor_defs()
                    for generator in gendata['generators']:
                        self._igen.append(generator)
                        if generator['std'] == 'iec60063':
                            rvalues = iec60063.gen_vals(
                                generator['series'],
                                iec60063.res_ostrs,
                                start=generator['start'],
                                end=generator['end'])
                            components = {}
                            for dcomponent in dcomponents:
                                if dcomponent.code in generator.keys():
                                    try:
                                        dcomponent.typeclass(
                                            generator[dcomponent.code])  # noqa
                                        components[
                                            dcomponent.code] = generator[
                                                dcomponent.code]  # noqa
                                    except:
                                        raise ValueError
                            for rvalue in rvalues:
                                pval = construct_resistor(resistance=rvalue,
                                                          **components)
                                values.append(pval)
                                if giseries is not None:
                                    giseries.add_value(rvalue, pval)
                        else:
                            raise ValueError
                if giseries is not None:
                    self._iseries.append(giseries)
                if 'values' in gendata.keys():
                    if gendata['values'][0].strip() != '':
                        values += gendata['values']
                        self._ivalues.extend(gendata['values'])
                if 'custom_series' in gendata.keys():
                    from tendril.conventions.series import CustomValueSeries
                    for name, series in viewitems(gendata['custom_series']):
                        if series['detail'].pop('type') != 'resistor':
                            raise ValueError('Expected a resistor series')
                        vals = series['values']
                        tsymbol = GedaSymbol(self._sympath)
                        iseries = CustomValueSeries(
                            name,
                            'resistor',
                            device=tsymbol.device,
                            footprint=tsymbol.footprint)
                        for type_val, val in viewitems(vals):
                            iseries.add_value(type_val, val)
                        iseries._desc = series['detail'].pop('desc')
                        iseries._aparams = series['detail']
                        self._iseries.append(iseries)
                        values.extend(vals.values())
                return values

            if gendata['type'] == 'capacitor':
                self._type = 'Capacitor'
                giseries = None
                for capacitance in gendata['capacitances']:
                    if capacitance is not None:
                        values.append(capacitance)
                        self._iunits.append(capacitance)
                if 'composite_series' in gendata.keys():
                    from tendril.conventions.series import CustomValueSeries
                    try:
                        name = gendata['composite_series']['name']
                        tsymbol = GedaSymbol(self._sympath)
                        giseries = CustomValueSeries(
                            name,
                            'capacitor',
                            device=tsymbol.device,
                            footprint=tsymbol.footprint)
                    except KeyError:
                        pass
                if 'generators' in gendata.keys():
                    dcomponents = jb_capacitor_defs()
                    for generator in gendata['generators']:
                        self._igen.append(generator)
                        if generator['std'] == 'iec60063':
                            cvalues = iec60063.gen_vals(
                                generator['series'],
                                iec60063.cap_ostrs,
                                start=generator['start'],
                                end=generator['end'])
                            components = {}
                            for dcomponent in dcomponents:
                                if dcomponent.code in generator.keys():
                                    try:
                                        dcomponent.typeclass(
                                            generator[dcomponent.code])  # noqa
                                        components[
                                            dcomponent.code] = generator[
                                                dcomponent.code]  # noqa
                                    except:
                                        raise ValueError
                            for cvalue in cvalues:
                                pval = construct_capacitor(capacitance=cvalue,
                                                           **components)
                                values.append(pval)
                                if giseries is not None:
                                    giseries.add_value(cvalue, pval)
                        else:
                            raise ValueError
                if giseries is not None:
                    self._iseries.append(giseries)
                if 'values' in gendata.keys():
                    if gendata['values'][0].strip() != '':
                        values += gendata['values']
                        self._ivalues.append(gendata['values'])
                if 'custom_series' in gendata.keys():
                    from tendril.conventions.series import CustomValueSeries
                    for name, series in viewitems(gendata['custom_series']):
                        if series['detail'].pop('type') != 'capacitor':
                            raise ValueError('Expected a capacitor series')
                        vals = series['values']
                        tsymbol = GedaSymbol(self._sympath)
                        iseries = CustomValueSeries(
                            name,
                            'capacitor',
                            device=tsymbol.device,
                            footprint=tsymbol.footprint)
                        for type_val, val in viewitems(vals):
                            iseries.add_value(type_val, val)
                        iseries._desc = series['detail'].pop('desc')
                        iseries._aparams = series['detail']
                        self._iseries.append(iseries)
                        values.extend(vals.values())
                return values
            elif gendata['type'] == 'wire':
                for gauge in gendata['gauges']:
                    for color in gendata['colors']:
                        values.append('{0} {1}'.format(gauge, color))
                return values
        else:
            logger.ERROR("Config file schema is not supported")
コード例 #35
0
ファイル: gedaproject.py プロジェクト: chintal/tendril
def gen_pcbpricing(projfolder, namebase, force=False):
    """
    Generates a PDF file with the pricing of the (bare) PCB provided by the
    gEDA project.

    The pcb file is the one listed in the gEDA project file, and the
    pcbname is the one specified in the
    :mod:`tendril.gedaif.conffile.ConfigsFile`. The pricing information is
    read out from the PCB's ``sourcing.yaml`` file, which in turn is intended
    to be created by sourcing modules.

    .. todo:: This function presently uses
              :func:`tendril.dox.render.render_lineplot`, which is marked for
              deprecation. It should be rewritten to use the
              :func:`tendril.dox.render.make_graph` route instead.

    :param projfolder: The gEDA project folder.
    :type projfolder: str
    :param namebase: The project name.
    :type namebase: str
    :param force: Regenerate even if up-to-date.
    :type force: bool
    :return: The output file path.

    .. rubric:: Paths

    * Output File :  ``<project_doc_folder>/<namebase>-pricing.pdf``
    * Source Files : ``<projectfolder>/pcb/sourcing.yaml``

    """
    gpf = projfile.GedaProjectFile(projfolder)
    pcbpricingfp = os.path.join(
        gpf.configsfile.projectfolder, 'pcb', 'sourcing.yaml'
    )
    pcbpricing_mtime = fsutils.get_file_mtime(pcbpricingfp)

    if not os.path.exists(pcbpricingfp):
        return None

    docfolder = get_project_doc_folder(projfolder)
    plotfile = path.join(docfolder, namebase + '-pricing.pdf')
    outf_mtime = fsutils.get_file_mtime(plotfile, fs=refdoc_fs)

    if not force and outf_mtime is not None and outf_mtime > pcbpricing_mtime:
        logger.debug('Skipping up-to-date ' + pcbpricingfp)
        return pcbpricingfp

    logger.info('Regnerating ' + plotfile + os.linesep +
                'Last modified : ' + str(pcbpricing_mtime) +
                '; Last Created : ' + str(outf_mtime))

    with open(pcbpricingfp, 'r') as f:
        data = yaml.load(f)

    workspace_outpath = workspace_fs.getsyspath(plotfile)
    workspace_folder = workspace_fs.getsyspath(path.dirname(plotfile))
    workspace_fs.makedir(path.dirname(plotfile),
                         recursive=True, allow_recreate=True)

    plot1file = os.path.join(workspace_folder, namebase + '-1pricing.pdf')
    plot2file = os.path.join(workspace_folder, namebase + '-2pricing.pdf')

    pltnote = "This pricing refers to the bare PCB only. " \
              "See the corresponding Config Docs for Card Pricing"

    plt1data = {key: data['pricing'][key]
                for key in data['pricing'].keys() if key <= 10}
    plt1title = gpf.configsfile.configdata['pcbname']
    plt1title += " PCB Unit Price vs Order Quantity (Low Quantity)"
    plot1file = render.render_lineplot(
        plot1file, plt1data, plt1title, pltnote
    )

    if max(data['pricing'].keys()) > 10:
        plt2data = {key: data['pricing'][key]
                    for key in data['pricing'].keys() if key > 10}
        plt2title = gpf.configsfile.configdata['pcbname']
        plt2title += " PCB Unit Price vs Order Quantity (Production Quantity)"
        plot2file = render.render_lineplot(
            plot2file, plt2data, plt2title, pltnote
        )
        pdf.merge_pdf([plot1file, plot2file], workspace_outpath)
        os.remove(plot2file)
    else:
        shutil.copyfile(plot1file, workspace_outpath)
    os.remove(plot1file)
    copyfile(workspace_fs, plotfile, refdoc_fs, plotfile, overwrite=True)
    return plotfile
コード例 #36
0
ファイル: order.py プロジェクト: chintal/tendril
    def _process(self, outfolder=None, manifestsfolder=None,
                 label_manager=None, register=False, force=False,
                 pb_class=None, stacked_pb=False, leaf_pb=True,
                 session=None):
        self._force = force

        if pb_class is None:
            pb_class = TendrilProgressBar

        if stacked_pb is True:
            pb = pb_class(max=8)
        else:
            pb = DummyProgressBar(max=8)

        pb.next(note="Constructing Resources for Production Order Generation")

        if outfolder is None:
            if self._order_yaml_path is not None:
                outfolder = os.path.split(self._order_yaml_path)[0]
            else:
                raise AttributeError('Output folder needs to be defined')

        if manifestsfolder is None:
            manifestsfolder = os.path.join(outfolder, 'manifests')
            if not os.path.exists(manifestsfolder):
                os.makedirs(manifestsfolder)

        if self._sno is None:
            self._sno = serialnos.get_serialno(
                    series='PROD', efield=self._title,
                    register=register, session=session
            )

        # Create Snomap
        if self._snomap_path is not None:
            with open(self._snomap_path, 'r') as f:
                self._snomap = SerialNumberMap(yaml.load(f), self._sno)
        else:
            self._snomap = SerialNumberMap({}, self._sno)

        self._snomap.set_session(session=session)
        if register is True:
            self._snomap.enable_creation()

        indent_sno = self._snomap.get_sno('indentsno')
        if register is True:
            serialnos.link_serialno(child=indent_sno, parent=self.serialno,
                                    verbose=False, session=session)

        # Create cards and deltas and so forth
        pb.next(note="Constructing Production Order Actions")
        actions = self.card_actions + self.delta_actions

        pb.next(note="Executing Production Order Actions")
        for action in actions:
            if register is False:
                action.scaffold = True
            action.set_session(session=session)
            action.commit(
                outfolder=manifestsfolder, indent_sno=indent_sno,
                prod_ord_sno=self._sno, register=register, session=session,
                pb_class=pb_class, stacked_pb=stacked_pb, leaf_pb=leaf_pb,
            )

        self._snomap.disable_creation()

        pb.next(note="Constructing Composite Output BOM")
        cobom = CompositeOutputBom(self.bomlist)

        # Assume Indent is non-empty.
        # Create indent
        pb.next(note="Creating Indent")
        indent = InventoryIndent(indent_sno, verbose=False, session=session)
        indent.create(cobom, title="FOR {0}".format(self.serialno),
                      desc=None, indent_type='production',
                      requested_by=self._ordered_by, force=force)
        indent.define_auth_chain(prod_order_sno=self.serialno,
                                 session=session, prod_order_scaffold=True)
        indent.process(outfolder=outfolder, register=register,
                       verbose=False, session=session)
        self._indents.append(indent)

        pb.next(note="Generating Production Order Document")
        # Make production order doc
        self._last_generated_at = arrow.utcnow().isoformat()
        if self._first_generated_at is None:
            self._first_generated_at = arrow.utcnow().isoformat()
        self._dump_order_yaml(outfolder=outfolder, register=register,
                              session=session)
        self._generate_doc(outfolder=outfolder, register=register,
                           session=session)

        pb.next(note="Generating Labels")
        self.make_labels(label_manager=label_manager, pb_class=pb_class,
                         stacked_pb=stacked_pb, leaf_pb=leaf_pb)

        pb.next(note="Finalizing Production Order")
        for action in actions:
            action.scaffold = False
            action.unset_session()
        self._snomap.dump_to_file(outfolder)
        self._snomap.unset_session()

        if register is True:
            docstore.register_document(
                    serialno=self.serialno,
                    docpath=os.path.join(outfolder, 'snomap.yaml'),
                    doctype='SNO MAP', efield=self.title,
                    verbose=False, session=session
            )
        pb.finish()
        self._defined = True