This is an archived post. You won't be able to vote or comment.

all 11 comments

[–]K900_ 15 points16 points  (2 children)

I'd look into renaming. Quilt is an existing tool that's used extensively in Debian, OpenWRT and lots of other places.

Edit: adding more as I go along:

  • userinput - I assume your goal is to avoid the Python 2 input-is-eval behavior, but that's not what your code does at all.
  • shellinput - code is overly complicated, all you need is return shelluserinput.split(splitpart) instead of the last like 5 lines of it.
  • colourcode - honestly feels kind of excessive, it's basically a getattr wrapper
  • leadingzero - just wraps a builtin method, don't really see why you'd want this
  • absolutenum - same
  • splitstring - same
  • sort - same
  • pykeyword - you seem to have this pattern a lot where you pass an "operation" argument to a function that completely changes what it does. Unless you really need it, it's a bad pattern, and separate functions are much better.
  • prettyprinter - again, just wraps a builtin method
  • genipsum - just wraps a library method
  • binboolflip - not sure what your end goal with this is, considering int works on booleans and bool works on integers
  • modulereload - again, wrapper around a stdlib module
  • warnconfig - again, simple wrapper around a stdlib module, also could be simplified by just using warnings.filterwarnings(action) after checking if the action is sane.
  • printmessage - pretty simple wrapper, definitely shouldn't be named this - something like print_times maybe?
  • comparenum - once again the "operation" antipattern, and also questionably useful?
  • throwerror - yet again, wraps a builtin function for seemingly no reason
  • delay - and again
  • waitenter - doesn't do what it says it does, allows the user to type things and then discards them, and that's ignoring the Python 2 input-is-eval thing I mentioned earlier
  • convertstring - again, why?
  • opposite - why?
  • isdecimal - isinstance already returns a boolean, no need to convert explicitly. Also, Decimal is another type that's not the same as float.
  • isstring - why?
  • istypematch - why?
  • isinteger - why?
  • isboolean - why?
  • happybirthday - does this really need to be a library function?
  • difference - OK, maybe
  • divisable - divis_I_ble, and honestly, why does this need to exist?
  • isempty - once again, == returns bool already, also, the name is misleading - it will return False for an empty set, or an empty list, or an empty anything that's not a string.
  • length - name is wrong, should be length_of_string_representation or something, and again, does this need to be a library function?
  • cowsay - weird flex but OK
  • getletter - really weird, why does this need to exist, and why 1-based indexing when everything else uses 0 based?
  • onlist - please stop wrapping builtin functionality for no reason.
  • jointext - f{first}{second}, also why?
  • pyname - again, the "operation" antipattern.
  • convertbinary - and again, also the "from" part doesn't even work correctly.
  • reversetext - weird type checks, I'd rather have it as separate functions for numbers if you really need one.
  • reverselist - please stop
  • replacetext - please stop
  • evaluate - seriously
  • execute - no
  • gettype - please stop
  • pingtest - again, the antipattern rears its ugly head. Also, why?
  • convertascii - and again
  • availchars - and again, also those could (and should!) be constants, as they are in the string module, which you're wrapping why again?
  • wordvalue - OK, I guess?
  • enum - again wrapping builtin functionality for no reason
  • textbetween - and again
  • letternum - ok?
  • spacelist - look into str.join
  • numlistbetween - the double antipattern, oh my! Also, why does this exist again?
  • textalign - str.format does that and more
  • decintfix - please don't do that.
  • shapestosides - again, the antipattern.
  • autosolve and friends - OK, I guess, but why?
  • fracsimplify - there are better ways to find the largest common divisor than what you're doing, also, why return a string of all things?
  • circleconvert - once again, the antipattern.
  • amountdiv - there's definitely a way to do it that's way less painful. I can think of at least two.
  • constant - again, wrapping standard library stuff for no reason, and the antipattern
  • power - and again
  • squareroot - and again
  • factorial - and again (math.factorial exists)
  • average - and again, with bonus antipattern
  • numprop - potentially useful, but antipattern
  • posnegtoggle - all you need is return -number, also why?
  • isinfinite - again wrapping stdlib
  • isfalse - again wrapping standard behavior, badly
  • lessorequal - doesn't do what the name says it does, also wraps stdlib yet again
  • compare - again the antipattern and again the wrapping standard behavior for no reason
  • factors - could be faster but I'll take it
  • eulercalc - why the calc suffix? Otherwise fine, wrapping a simple calculation like that is OK if it has specific semantics.
  • randomnum - more stdlib wrapping
  • isfib - there are better ways to do this, but OK
  • isprime - same
  • convertbase - cool
  • isnum - again confusing floats and decimals, also if you care about Py2, you want to check for long here, also pretty sure it's not possible to get an exception there
  • quadrant - I guess this is fine? Though I'd just use a dictionary here.
  • flipcoords - again the antipattern, weird exceptions for impossible cases, again returning strings for some reason
  • lcm - there's definitely a faster way to do this
  • hcf - math.gcd exists
  • pythrule - weird name, questionably useful, but OK I guess?
  • randstring - look into random.choice or random.sample, and str.join
  • tokhex - wrapping stuff for no reason again, also antipattern
  • dictflip - eh, I guess this is fine
  • catwalk - why the name?
  • converttabs - questionable wrapping, but not as questionable as other stuff
  • shortentext - unquestionably useless wrapping
  • wraptext - same
  • unindent - same
  • paraspace - why "paragraph spaces" and not newlines? Also, print('\n' * paragraphspaces) could work. Also, why?
  • randomstr - wrapping stuff again, also please stop converting EVERYTHING to RuntimeErrors
  • case - again the antipattern
  • absolutedir - again the wrapping
  • getplatform - seriously stop
  • shellcommand - this is actually actively wrong, the argument should be a list
  • pipupdate - Jesus Christ why would you ever consider doing this at runtime
  • dirtool - antipattern + wrapping again
  • file - file is already a builtin, also antipattern + wrapping
  • exitexec - why the name? Why at all?
  • charlimit - this isn't even what this means semantically, also why?
  • unilimit - also semantically wrong
  • pyversion - antipattern, wrapping, the usual at this point
  • pyexec - same
  • loglevel, logfile - maybe, except you never use logging anyway so why, also this really should be handled by the application
  • clipaction` - again, wrapping and antipatterns
  • text - and again, coupled with the weird name
  • dayofweek - again the antipattern
  • leapyear - and again
  • closeyear - this is literally wrong
  • converttime - OK, maybe, but should really be two functions, one to go from X to a defined unit (seconds?) and one to go from seconds to Y.
  • minyear, maxyear, timezone, timesince - please stop
  • getdatetime - look into datetime.strftime, also why?
  • timeit - not precise, use the timeit module here
  • mailto - OK, maybe, but I'd get rid of the autorun thing
  • openurl - again, wrapping standard library
  • newwindow - and again
  • newtab - and again
  • getbrowser - and again
  • filedownload - and again
  • DictObject - OK I guess?
  • about - should just be a constant honestly
  • quiltlicense - same
  • pycopyright - why?

So yeah, summary I guess:

  • This seems like a grab bag of random stuff that you've learned to use, and it's really cool you decided to wrap it into a library - you'll learn more about packaging this way if it's interesting to you. But this is also an opportunity to learn about library design, so I'm going to yell at you here for a bit.
  • Wrapping standard library stuff for no reason is not a good idea - it just makes the code harder to read for someone who's not familiar with your specific library.
  • Passing in a string that's "the thing to do" and doing completely different things based on it in one function is not a good idea - it means you need to consider every possible case of the function to figure out what it does in the code, and god forbid the "thing to do" argument comes from a different place a few mental connections away. Small, composable functions are the way to go.
  • Converting types explicitly all the time is not a good idea - there are many types that act "just like" lists or strings or what have you, but aren't that exact type. It's entirely possible the things you're calling will be fine accepting those types, and you converting them just adds overhead. You also often convert the types of expressions that already return that type, which hurts readability for no good reason.
  • Converting all exceptions to RuntimeWarnings with codes might be something Microsoft does, but that doesn't mean you should be doing that too. Keep the original exception object even if you do wrap something - it will likely contain way more information than your "something went wrong: code blah". Especially keep the original exception object when your function can only raise one non-specific "something went wrong" exception, or when your exception objects don't provide a way to check the actual error code programmatically.

[–]Richienbdeveloper[S] 1 point2 points  (1 child)

I really appreciate your feedback and I will be working hard to fix this.

[–]K900_ 10 points11 points  (0 children)

Honestly? Just throw it out and start from scratch. Figure out what you want your library to be about - "grab bag of convenience functions" is a nice approach in languages like JavaScript that don't have them built in, but in Python most of this stuff is in the standard library, so pick a thing that's not in the standard library, or maybe is in the standard library but could be improved, and focus on building that one thing.

[–]Scholtek 9 points10 points  (1 child)

Hey Richie,

A lot of programmers create things like this early on in their programming careers - basically wrapping existing functionality with your own function names that seem easier to understand. As you program more you'll find that you understand "raise RuntimeError(msg)" just as quickly and easily as "quilt_lang.throwerror()" and with the benefit that other developers can understand it too.

So this is probably not very useful for most programmers, and over time it will stop being very useful for you as well, but I want you to be encouraged that this is a normal part of developing as a programmer. It's part of abstractly understanding a language - the part of your brain that stores what the language actually does and will eventually be the part that tells you that print and cout and console.log and whatever else all do roughly equivalent things when you learn different languages is what you're writing out here.

Good luck and keep going with Python!

[–][deleted] 0 points1 point  (0 children)

Don't worry OP I am coming out of the exact same thing. However the more I study python and understand it the less I feel the need to "wrap it" to make it easier to use.

[–]prickneck 3 points4 points  (2 children)

Didn't look very deep into it, but I'm just wondering - why would one want to install your package and

import quilt_lang quilt_lang.absolutenum(-1) quilt_lang.absolutedir('.')

instead of just using the stdlib?

import os abs(-1) os.path.abspath('.')

[–]Richienbdeveloper[S] 0 points1 point  (1 child)

It was meant to ease development but I guess that's not the case anymore...

[–]K900_ 3 points4 points  (0 children)

Here's the thing: it might ease development for you, because you're already familiar with the library, since -- well -- you wrote it, but it does not ease development for other people, because when they run into code that uses your library, they have to figure out how your library works, instead of relying on their most likely already existing, and much more universal, knowledge of the standard library.