git – First published Python module, how is my project/code structure?

So I’ve just finished my first Python module (and published on Github), with this little project I’d like to learn how to distribute my code so that other users can use it as a plug in for their own projects.

Specifically I’m looking for feedback in the following direction:

  • Is the interface to the module designed correctly?
  • At the beginning of the code I check for completeness of the input, is this the best way to handle errors? (It looks chunky)
  • Is the repository set up correctly so that it is plug-and-play?
  • In general, is this the best way to design a module or should I work with classes instead of funtions?

Any other feedback is also welcome 🙂

Thanks in advance!


Link to Github repository: https://github.com/nick-van-h/cutlistcalculator

__main__.py:

from cutlist import getCutLists
import sys
import argparse

if __name__ == '__main__':
    #Argument parser
    text = "This program calculates the most optimal cutlist for beams and planks."
    parser = argparse.ArgumentParser(description=text)
    parser.add_argument("-i", "--input", help="custom location of input json file (e.g. 'localhost:8080/foo/bar.json'", default="")
    parser.add_argument("-o", "--output", help="custom location of output folder (e.g. 'localhost:8080/foo' -> 'localhost:8080/foo/cutlist_result.json'", default="")
    args = parser.parse_args()

    #Kick-off
    result = getCutLists(args.input, args.output)

    #Exit function with VS Code workaround
    try:
        sys.exit(result)
    except:
        print(result)

cutlist.py:

import json
from operator import itemgetter
import copy
from pathlib import Path
import os

def getSolution(reqs, combs):
    needs = copy.deepcopy(reqs)
    res = ()
    res.append(())
    for comb in combs:
        #As long as all items from comb(x) fulfill need
        combNeed = True
        while combNeed:
            #Check if comb(x) provides more than need (fail fast)
            for need in needs:
                if comb(need('Length')) > need('Qty'):
                    combNeed = False
            if not combNeed:
                break

            for need in needs:
                need('Qty') -= comb(need('Length'))

            #Append result
            res(0).append(comb.copy())

    #Calculate total price
    for sol in res:
        price = round(sum(x('Price') for x in sol),2)

    res.append((price))

    #Return result
    return res

def getCutLists(inputstr = "", outputstr = ""):
    if inputstr:
        jsonlocation = inputstr
    else:
        jsonlocation = './input/input.json' #default input location
    print(jsonlocation)
    errstr = ""

    #Get input
    try:
        with open(jsonlocation) as f:
            data = json.load(f)
    except:
        errstr += "JSON file not found. "
        return(f"Err: {errstr}")

    #Get variables from JSON object
    try:
        reqs = data('Required Lengths')
    except:
        errstr += "'Required Lengths' not found. "

    try:
        avail = data('Available base material')
    except:
        errstr += "'Available base material' not found. "

    try:
        cutwidth = data('Cut loss')
    except:
        errstr += "'Cut loss' not found. "

    if errstr:
        return(f"Err: {errstr}")

    #Test for required keys in array
    try:
        test = (x('Length') for x in reqs)
        if min(test) <= 0:
            errstr += f"Err: Required length ({min(test)}) must be bigger than 0."
    except:
        errstr += "'Length' not found in required lengths. "

    try:
        test = (x('Qty') for x in reqs)
        if min(test) <= 0:
            errstr += f"Err: Required quantity ({min(test)}) must be bigger than 0."
    except:
        errstr += "'Qty' not found in required lengths. "

    try:
        test = (x('Length') for x in avail)
        if min(test) <= 0:
            errstr += f"Err: Available length ({min(test)}) must be bigger than 0."
    except:
        errstr += "'Length' not found in available base material. "

    try:
        test = (x('Price') for x in avail)
        if min(test) < 0:
            errstr += f"Err: Available price ({min(test)}) can't be negative."
    except:
        errstr += "'Price' not found in available base material. "

    if errstr:
        return(f"Err: {errstr}")


    #Init other vars
    listreq = (x('Length') for x in reqs)
    listavail = (x('Length') for x in avail)
    minreq = min(listreq)
    res=()

    #Error handling on passed inputs
    if max(listreq) > max(listavail):
        return(f"Err: Unable to process, required length of {max(listreq)} is bigger than longest available base material with length of {max(listavail)}.")

    if cutwidth < 0:
        return(f"Err: Cut width can't be negative")

    #Make list of all available cut combinations
    combs = ()
    for plank in avail:
        myplank = plank.copy()
        for cut in reqs:
            myplank(cut('Length')) = 0

        #Increase first required plank length
        myplank(reqs(0)('Length')) += 1

        #Set other variables
        myplank('Unitprice') = myplank('Price') / myplank('Length')

        filling = True
        while filling:
            #Calculate rest length
            myplank('Rest') = myplank('Length')
            for i in reqs:
                length = i('Length')
                myplank('Rest') -= ((myplank(length) * length) + (myplank(length) * cutwidth))
            myplank('Rest') += cutwidth

            #Set rest of variables
            myplank('Baseprice') = (myplank('Price')) / ((myplank('Length') - myplank('Rest')))
            myplank('Optimal') = (myplank('Rest') <= minreq)


            #Check if rest length is positive
            if myplank('Rest') >= 0:
                combs.append(myplank.copy())
                myplank(reqs(0)('Length')) += 1
            else:
                for i in range(len(reqs)):
                    if myplank(reqs(i)('Length')) > 0:
                        myplank(reqs(i)('Length')) = 0
                        if i < len(reqs)-1:
                            myplank(reqs(i+1)('Length')) += 1
                            break
                        else:
                            filling = False

    #Sort combinations descending by remaining length, get solution
    combs = sorted(combs, key=lambda k: k('Rest'))
    res.append(getSolution(reqs, combs))

    #Sort combinations by getting biggest lengths first (largest to smallest), optimal pieces first, get solution
    listreq = sorted(listreq, reverse=True)
    listreq.insert(0,'Optimal')
    for x in reversed(listreq):
        combs.sort(key=itemgetter(x), reverse=True)
    res.append(getSolution(reqs, combs))

    #Sort combination by least effective price per unit, get solution
    combs = sorted(combs, key=lambda k: k('Baseprice'))
    res.append(getSolution(reqs, combs))

    #Get cheapest option & make readable format
    cheapest = min((x(1) for x in res))
    for x in res:
        if x(1) == cheapest:
            sol = {}
            sol('Required base material') = {}
            sol('Cut list') = ()
            i = 1
            for plank in x(0):
                if plank('Length') not in sol('Required base material'):
                    sol('Required base material')(plank('Length')) = 0
                sol('Required base material')(plank('Length')) += 1
                str = f"Plank {i}: Length {plank('Length')}, "
                for req in reqs:
                    if plank(req('Length')) > 0: str += f"{plank(req('Length'))}x {req('Length')}, "
                str += f"rest: {plank('Rest')}"
                sol('Cut list').append(str)
                i += 1

            sol('Total price') = cheapest
            break

    #Get output location
    if outputstr:
        outputfile = outputstr
        if outputfile(len(outputfile)-1) != "//":
            outputfile += "//"
        outputfile += "cutlist_result.json"
    else:
        outputfile = "./output/cutlist_result.json"

    #Make directories
    Path(os.path.dirname(outputfile)).mkdir(parents=True, exist_ok=True)

    #Output to file
    f = open(outputfile, "w")
    json.dump(sol, f, indent=4)
    f.close

    return("Success")

magento2 – Is it acceptable to put lib folder inside module folder structure?

Before I used this code to include some packages:

require_once($this->dir->getPath('lib_internal') . '/vendor/module/nuevomailer/api.php');

Now Magento doesn’t allow to use require_once anymore so I thought that the simplest way without creating another packages just for third party libraries would be to just create lib folder inside existing vendorname/modulename folder and call it like this:

    class Subscriber extends MagentoFrameworkModelAbstractModel{
        protected $mailchimp;
        protected $phpmailer;
        ...
        public function _construct(
            VendornameModulenameLibMailchimp $mailchimp,
            VendornameModulenameLibPhpmailer $phpmailer,
            ...
        function subscribe(){
            $this->mailchimp->subscribe();
        }

Is that acceptable method? I checked Magento modul file structure (https://devdocs.magento.com/guides/v2.3/extension-dev-guide/build/module-file-structure.html) and I couldn’t find lib folder. Is it allowed to put any other folder into module directory?

python – Using a dictionary template for consistent response structure from an API

There is no need to use deepcopy here. Just have a function that returns a new object when you need it. And while you’re at it, just make the message and the result parameters of that function. Or even all of them:

def json_response(message, result, status="ok", code=0, error=False):
    return {
        "status" : status,
        "code" : code,
        "error" : error,
        "message" : message,
        "result" : result
    }

@route('/example')
def example():
    result = {
        "title" : "Test Title",
        "body" : "<p>Lorem ipsum dolor sit amet...</p>"
    }
    return json_response("Success", result)

Having all as parameters, but with default values, allows you to do this in the future:

json_response("Failure", None, status="fail", code=404, error=True)

In the end it depends on how often you need to use this template whether or not this is better than just directly returning the dictionary explicitly:

@route('/example')
def example():
    return {
        "status" : "ok",
        "code" : 0,
        "error" : False,
        "message" : "Success",
        "result" : {
            "title" : "Test Title",
            "body" : "<p>Lorem ipsum dolor sit amet...</p>"
        }
    }

redirect – URL re-direct (without changing the structure)

On my site, when I go to www.example.com/aaa/bbbbbb/ and click on “ccccccccc“,

I get: www.example.com/aaa/bbbbbb/ccccccccc

Instead, I need the URL to look like this:

www.example.com/ccccccccc

Without changing the structure in WP (I need it for breadcrumbs)

options – What structure and database storage method should I use for temporary storage that may be written concurrently?

In working with a third-party API, I need to store some state information to help track a process. I’m wondering where and how I should store it.

Specifically, I have a multi-page Gravity Form, and using the hooks they provide, I’m submitting a POST request to an API once the first page is filled out, getting back a unique ID, and then submitting the fields from the second page to the API with a PATCH request. (There are good reasons for this seemingly complex flow.)

I have a unique ID for the form submission, and a unique ID for the API record that’s created and then needs to be updated. What I’m looking for is the best way to connect that information in the database so that when the second page of the form is completed, I know which API record should be updated.

I’ve considered using the Transients API, since this is by definition a very temporary storage need, but since the data is not guaranteed to be there when I need it, I don’t think it will work.

I’m leaning towards using an associative array (with the unique form ID as the key) with the Options API. My concern: if I have dozens or even hundreds of people filling out this form at the same time, is there a risk of race conditions or similar issues in writing to one option? Should I break this out into one option per form submission? Or create a separate table similar to the postmeta table?

Or am I overthinking this, and a single array in an option will be just fine?

reference request – A terminology related to the definition of a mathematical structure

At the moment I am writing a textbook in Foundations of Mathematics for students and trying to give a precise definition of a mathematical structure, which is the principal notion of structuralist approach to mathematics, formed by Bourbaki. Intuitively (and on many examples) the notion of a mathematical structure is clear: this is a pair $(X,S)$ consisting of a set $X$, endowed with a structure $S$, which is a set somehow related to $X$. This relation of $S$ to $X$ is well-defined for first-order theories, which use the notion of a signature. What about the general case?

I arrived the the following definition and would like to ask some terminological questions.

The main idea is that a mathematical structure is determined by a pair $(sigma,mathcal A)$ consisting of a set $sigma$ called the signature and a list $mathcal A$ of $sigma$-axioms. By a $sigma$-axiom I understand a pair $(varphi,c_varphi)$ consisting of a formula $varphi$ whose free variables are in the list $x,s,g,c$, and a set $c_varphiin sigma^{<omega}=bigcup_{ninomega}sigma^n$.

So $c_varphi$ is some fixed tuple of elements of the signature $sigma$.
Therefore, a $sigma$-formula $(varphi,c_varphi)$ can be interpreted as a formula with free variables $x,s$ and some fixed parameters in the set $sigmacup{sigma}$.

Definition. A mathematical structure of type $(sigma,mathcal A)$ is any ordered pair of sets $langle X,Srangle$ such that for any $sigma$-axiom $(varphi,c_varphi)inmathcal A$, the formula $varphi(X,S,sigma,c_varphi)$ is satisfied.

The set $X$ is called the underlying set of the mathematical structure $langle X,Srangle$ and the set $S$ is called its structure.

In the list $mathcal A$ of $sigma$-axioms we can encode all desired properties of the structure $S$, for example that it is an indexed family $(S_i)_{iinsigma}$ and for some $iinsigma$ the set $S_i$ is a binary operation on $X$ satisfying such-and-such axioms, whereas for another $jinsigma$, $S_j$ is a relation on the power-set of $X$ (for example, satisfying the axioms of topology) etc, etc.

The question is how to call the pairs $(sigma,mathcal A)$ determining a type of a mathematical structure? Which properties of the list $mathcal A$ of $sigma$-axioms guarantee that mathematical structures of type $(sigma,mathcal A)$ form a category (for some natural notion of a morphism between mathematical stuctures of the same type $(sigma,mathcal A)$)?

I have a strong suspicion that such questions has been already studied (and some standard terminology has been elaborated), but cannot find (simple) answers browsing the Internet. I would appreciate any comments on these foundational questions.

python – Some Folder path to Tree structure

There is some path, it is list structure, like:

a=("/desktop/folderA/fileA","/desktop/folderA/folderX/file1","/diskKH/folderA/fileA","/desktop/folderB/folderC/fileX")

It can be:

({
    'name': 'diskC',
    'children': ({
        'name': 'folderA',
        'children': ({
            'name': 'test_file'
        }, {
            'name': 'sub_folderX',
            'children': {
                'name': 'file1'
            }
        })
    }, {
        'name': 'folderB',
        'children': {
            'name': 'folderC',
            'children': {
                'name': 'fileX'
            }
        }
    })
}, {
    'name': 'diskKH',
    'children': {
        'name': 'folderA',
        'children': {
            'name': 'test_file'
        }
    }
})

I use this way:

import copy
def ChageArraryInverted(arrary):
    dict_1={}
    for index in range(len(arrary)-1,-1,-1):
        dict_1("name")= arrary(index)
        dict_2=copy.copy(dict_1)
        dict_1("children")=dict_2
    return dict_1("children")

def GetResArrary(arrary):
    list_all=()
    for item in arrary:
        item=str(item).split("/")(1::)
        item=ChageArraryInverted(item)
        list_all.append(item)
    print(list_all)
    return list_all



import pysnooper
# @pysnooper.snoop()

def Merge(dict1, dict2):
    result = copy.copy(dict1)
    if isinstance(dict1,dict):
        if dict1("name") == dict2("name"):
            if 'children' in dict1 and 'children' in dict2:
                if isinstance(dict1("children"), dict):
                    if dict1('children')('name') == dict2('children')('name'):
                        result('children') = (Merge(dict1('children'), dict2('children')))
                    else:
                        result('children') = (dict1('children'), dict2('children'))
                if isinstance(dict1("children"), list):
                    for index in range(0, len(dict1("children"))):
                        if dict1('children')(index)('name') == dict2('children')('name'):
                            result('children') = (Merge(dict1('children')(index), dict2('children')))
                        else:
                            if dict2('children') not in result('children'):
                                result('children').append(dict2('children'))
            elif 'children' in dict1:
                result('children') = (dict1('children'))
            elif 'children' in dict2:
                result('children') = (dict2('chidlren'))
            else:
                if "children" in result:
                    del result('children')
            return result
        else:
            result = (result, dict2)
            return result
    elif isinstance(dict1,list):
        for index in range(0,len(dict1)):
            if dict1(index)("name") == dict2("name"):
                if 'children' in dict1(index) and 'children' in dict2:
                    if isinstance(dict1(index)("children"), dict):
                        if dict1(index)('children')('name') == dict2('children')('name'):
                            result('children') = (Merge(dict1(index)('children'), dict2('children')))
                        else:
                            result('children') = (dict1(index)('children'), dict2('children'))
                    if isinstance(dict1(index)("children"), list):
                        for index in range(0, len(dict1(index)("children"))):
                            if dict1(index)('children')(index)('name') == dict2('children')('name'):
                                result('children') = (Merge(dict1(index)('children')(index), dict2('children')))
                            else:
                                if dict2('children') not in result(index)('children'):
                                    result(index)('children').append(dict2('children'))
                elif 'children' in dict1(index):
                    result(index)('children') = (dict1(index)('children'))
                elif 'children' in dict2:
                    result(index)('children') = (dict2('chidlren'))
                else:
                    if "children" in result(index):
                        del result(index)('children')
                return result
            else:
                result = (result, dict2)
                return result

def CirArraryToResult(list):
    re={}
    for index in range(0,len(list)):
        if index<len(list)-1:
            if len(re)==0:
                re=Merge(list(index),list(index+1))
            else:
                if(index==len(list)-1):
                    return re
                re=Merge(re,list(index+1))
    return re
a=("/desktop/folderA/fileA","/desktop/folderA/folderX/file1","/diskKH/folderA/fileA","/desktop/folderB/folderC/fileX")
res=GetResArrary(a)
res=CirArraryToResult(res)
print("res:",res)

But I think there are more efficient algorithms, what can I do to improve it? thank you

java – Package organization and project structure design

I am trying to create a text searcher library in java, that will have an interface TextSearcher and 3 classes implementing it: RegexPatternSearcher, SingleTokenSearcher and MultiTokenSearcher

I then created a TextSearcherFacade class that exposes static methods like:

  1. static findEmailAddresses(String input) – uses RegexPatternSearcher
  2. static findPhoneNumbers(String input) – uses RegexPatternSearcher
  3. static findDisallowedWords(String input, Set<String> disAllowedWords) – uses SingleTokenSearcher

I want users of the library to have these (i.e. methods from TextSearcherFacade) simple methods exposed for ease of use.

However, I don’t like the idea of a single TextSearcherFacade class with methods that configure and create the RegexPatternSearcher, SingleTokenSearcher and MultiTokenSearcher because these methods depend on different classes and seem logically different.

I am trying to look for a better and more extensible way to design this library. Any help is greatly appreciated.

Catalog Products List widget Magento 2.3 folder structure

I'm using Magento 2.3.3 and I'm looking for the folder structure of the Catalog Products List widget to see the code. I have tried searching the / var / www / html / vendor / magento folders but have not found it.

Inheritance or structure in structure

I wonder what the difference is between:

structure A

{

struct B {};

};

and:

struct A {};

structure B: A {};

Thanks for the answers!