• bennr01

    @danaportenier replace def __ini__(...) with def __init__(...) (notice the t)

    Edit: You can also replace your if-construct with something like this:

    inp = input("What was the month (1-12) ").strip()
    self.month_input = {
       "01": 1,
       "1": 1,
       "Jan": 1,
        "02": 2,
        "2": 2,
        "Feb": 2,
        }.get(inp, None)

    This does the following:

    1. ask the user for input, saving it in the local variable inp
    2. create a dictionary (key-value mapping) containing the inputs and their numeric values, then checks if inp is in the dictionary. If it is, the value for the input is assigned to self.month_input, otherwise the value None is used.

    I would also recomment to restructure the code as follows:

    class UserInputDate(object):   # inherit from object, use PEP8-style naming conventions
        MONTH_TO_YEAR = {...}  # your month names to values, as dicussed above
        def __init__(self, month, year):
            self.month = self.MONTH_TO_YEAR.get(month, None)   # do not call I/O functions from `__init__`. You may later need the same class without input.
            self.year = year
        def from_input(cls):
            # use a classmethod to directly create the class from input
            month = input("Please enther month (1-12)")
            year = input("Please enther year")
            return cls(month, year)
        def combine(self):
             # as your old code, but using self.month and self.year
    if __name__ == "__main__":
        # place top-level code inside such an if-statement, so it does not get executed on import
        primary_bariatric_date = UserInputDate()

    The above code is not tested, but it should prove you with some tips regarding class layout.
    Most of these changes seem useless at first, but are more useful later on.

    posted in Pythonista read more
  • bennr01

    It is a new StaSh bug. I do not know the exact details, but it seems like StaSh only creates an empty file for the command. This may be caused by a recent change. Could you please provide the output of the version command?

    posted in Pythonista read more
  • bennr01

    @ccc I also oppose dropping python 2 from pythoniststa 3 for several reasons.

    1. I still have a huge amount of py2 code which i do not want to port
    2. I do not want to be forced to adapt py3. While i am slowly, but steadily switching over to py2 and py3 compatible source and later to only py3, i want to do this on my own pace and not suddenly because one of my most used apps dropped support for py2.
    3. Pythonista 3 is advertised on the appstore as being both py2 and py3 compatible. Some people, including me, probably would not have bought pythonista3 if it did not support py2. Before @omz announced that pythonista3 would support both versions, I had not even considered buying pythonista3. Chances are, that a few people may be outraged if py2 was dropped. You may argue that they do not have to update, but maybe some people have automatic updates on and will know py2 was dropped before it is too late. And i do not want to see that shitstorm.
    4. Why should we even drop py2? Just because it is officialy EOL does not mean we have to drop support for py2. While it would be nice if we would have a faster start-up time, a simple do not load py2/py3 switch would also do the job.
    5. I sometimes work on py2 code on my iPhone and like it.
    6. Py3 is an abomination which i will fight until my very last breath.

    Well, in the end it is the decision of @omz .

    posted in Pythonista read more
  • bennr01

    @sendog3c could you please provide a bit more information about your problem?

    But I have problem with parameter, data gotten from sender (str, int).

    What exactly do you mean? sender.title should always be a str. If you want to convert a str to an int, use int(text_here). If you want to convert a int to a str, use str(int_here).

    def button_tapped(sender):
        #if  button_tapped == b_top1.title('SUM'):
        #itexto1 = 'Hello World'
        texto1 = sender.title
        #texto1 = str(300)  
        return texto1

    You can not return something from a callback. Instead, do the operation directly in the callback.
    An example:

    def button_tapped(sender):
        a = ...  # value for a here
        b = ...  # value for b here
        action = sender.title
        if action == "SUM":
            result = a + b
        # .. other operations
        txt_field1.text = str(result)

    Also, the following will not work:

    txt_field1.text = button_tapped()

    If i understand correclty, you want to change the text when a button was pressed. However, button_tapped() will be evaluated right in this line, before the UI is presented. Instead, modify the text in the callback as shown above.

    posted in Pythonista read more
  • bennr01

    @Robert-Buckley said:

    because once those controls have been used, they disappear and don't come back.

    Uhmm... what? This is not supposed to happen...

    posted in Pythonista read more
  • bennr01

    The option for cursor color is called tint color (or something like that). Also, like @ccc said, restart the app after making changes.

    posted in Pythonista read more
  • bennr01

    @Robert-Buckley there is also the easy_config command, which allows changing the colors

    posted in Pythonista read more
  • bennr01

    @shtek said:

    why not merged yet?

    It is now merged.

    it's utf8 everywhere, why stick to python 2

    If your question is "why is StaSh still py2 and not yet py3?", then there are two reasons:

    1. Large codebase, some of it using py2-only or outdated dependencIes (e.g.g git)
    2. The person who did most of the current port to py3 finally understood that py3 is an abomination which needs to be fought until our very last breath

    posted in Pythonista read more
  • bennr01

    @headsphere You could try disabling wheels for the installation using pip --verbose install --no-binary :all: attrs.

    posted in Pythonista read more
  • bennr01

    Hi, have you checked the physical mute switch on your phone? There should be a switch near the volume buttons, which, wenn activated, mutes specific sounds including most of pythonista sounds.

    posted in Pythonista read more
  • bennr01

    @JonB said:

    BTW, iirc, monkeylord in stash has the capability to "mount" Google drive folder.

    The mount-command currently only supports dropbox, ftp, zipfiles and other directories. I am thinking about rewriting it to use pyfilesystem2 instead, but this may still take a while.

    @FarmerPaco said:

    I did check the site packages and saw the Stash running 2.7 installs a more updated version of pyasn1 (v. 2.1) where as stash runing at 3.6 installs an earlier version of pyasn1 (v.1.7). This seemed strange.

    Interesting... Are you using StaSh version 0.7.2? I recently changed pip to respect the python version when installing new packages, but pyasn1 should work for both... Also, are you sure about the version of pyasn1? According to pypi the most recent version is 0.4.5.

    posted in Pythonista read more
  • bennr01

    @djl said:

    "-s d blabla" are necessary arguments in this example . I cannot figure out how to do the same thing from the Pythonista console.

    You can long-press the run-Button to add arguments

    Regarding the SyntaxError: Maybe you run StaSh in a different python version than the console?

    posted in Pythonista read more
  • bennr01

    @Drizzel it seems like Document.generate_pdf() uses subprocess to spawn a seperate process for generating the PDF. This is not allowed by iOS, thus the error.

    posted in Pythonista read more
  • bennr01

    @adrius42 said:

    Why??! This feels very counter-intuitive changing the meaning of equals in this way.
    I guess way back in the mists of time the original Python developer had a reason!
    So actually the operator was the time traveller! (Or rather the temporal cloner!)

    IIRC, most languages do this. It allows some usefull stuff which would otherwise be impossible.
    For example, assume you had the following code:

    def add_defaults(l):
        """add some default values"""
        if "value_default" not in l:
    def remove_invalid_values(l):
        """remove all invalid values from list"""
    some_values = ask_user_for_input()

    Due to having the same list shared between the functions, we can avoid unneccessary assignments. This is both easier and way more efficient.

    But the more important reason is consistency: list are objects. This is the same in many programming languages due to the way they work. And all non-primitve objects (maybe there are some exceptions, but none important) are not directly assigned to a variable. Instead, when you say some_object = SomeObject(), SomeObject() is created somewhere in your RAM and a reference is created which points to SomeObject(). This reference is then assigned to some_object. When you use some_var = some_object, some_var actually gets a copy of the reference, like some_var = some_int would do, but the copy of the reference still points to the same object. Thus, even if some_var is a copy of the reference in some_object, it still points to the same object.
    Maybe this code can explain this a bit better:

    class SomeClass(object):
        """some class"""
        def __init__(self, v):
            v = v
    int_var_a = 1  # int_var_a is directly assigned the integer 1
    int_var_b = int_var_a  # int_var_a is loaded, and the content is assigned to int_var_b
    print(int_var_a == int_var_b)  # True, both are equal
    int_var_a = 2
    print(int_var_a == int_var_b)  # False
    obj_var_a = SomeClass("value_1")  # an instance of SomeClass() is created and stored in the RAM. A reference pointing to SomeClass() is created and assigned to obj_var_a
    obj_var_b = obj_var_a  # the >reference< if obj_car_a is copied to obj_var_b
    print(obj_var_a.v == obj_var_b.v)  # True, because both obj_var_* point to the same object
    obj_var_b.v = "some other value"  # the object is modified, but both obj_var_* still point to the same object
    print(obj_var_a == obj_var_b)  # True, because both obj_var_* still point to the same object and both have been modified

    I am getting ever more convinced that I do not understand the operation of “self”
    Can you point me to some text that would help me... it feels like self is not always self, and often self is “not defined’ when I know it had been!?

    self is in fact not a operation, but a variable name without any real meaning.
    Here is some more code:

    class MyClass(object):
        def method_a(self, x):
            # self points to the instance of MyClass() this method is called on. x is some other value
        def method_b(foo, x):
            # foo points to the instance of MyClass() this method is called on. x is some other value
            # this is because the first parameter of a bound method is always the object
        def some_static_method(x):
            #This is a static method. self is not defined here. x is some other value passed to this method.
        def some_class_method(cls, x):
            # This is a class method. cls is not pointing to the instance of the object this is called on, but instead pointing to the class this is called on.
            # this is useful for alternative constructors

    In other words: self is always defined if you name the first parameter/argument of a bound (more about that later) method self. If you name the first parameter/argument of a bound method foo, then foo would be the equivalent of self.
    A bound method is a normal method of an instance of a class. In the above example, MyClass().method_a and MyClass().method_b are bound methods, because they are "normal" methods (not modified by @staticmethod or @classmethod) of an instance (MyClass()).
    If you use MyClass.method_a or MyClass.method_b (please note the missing (), this is the class, not instances of the class), these are unbound methods, as they are not part of an instance. In this case, self must be specifically passed to the method.

    Also, about self: you can think about self as some sort of namespace. self is unique per instance of a class. Changes to self persist between methods of the same instance, but not between methods of different instances.

    I would have preferred
    B = A transferred contents of A to B just thus once
    B == A results in B becoming the same as A for all time

    In python, == means a comparsion of equality.

    But then I am just wishing that the Python Language understood me, rather than me having to understand it!

    Dont worry, you are not the only one...

    To be clear this only applies to lists right?

    A = 1
    B = A
    A = 2
    Won’t change B to 2

    So, are there any other types of variables where the operators change what they do?

    This behavior applies to all non-primitive types.
    Some example of primitive types are int, long and float.
    Non-primitive types are basically everything else, mostly instances of classes.
    So, a={}; b=a; b["a"] = 2 would also modify a.
    a=1; b=a; b=2 would not change a, because both b and a are primitive.
    Strings are interesting. They are objects, but immutable. a=""; b=a; some_change(b) would change a too, but since neither a nor b can be changed, this is not a problem.

    Small disclaimer: I am not involved with the development of python and can thus not guarantee that the above information is correct, but it should be.

    Sorry for my bad english, it is not my native language. I still hope that this may be of help for you.

    posted in Pythonista read more
  • bennr01

    @JonB There is currently no flag, but you can switch priority in line 1051 of pip.py. But the flag is a good idea, I'll add it when/if i fix Wheels for PEP 491.

    posted in Pythonista read more
  • bennr01


    I've been having some odd issues with stash as of late, most annoyingly is that it's started ignoring when I type a space with an external keyboard.

    Are you using the pythonista beta?

    Is there any other way to install modules? Something a bit more native to the app? That's 90% of what I had been using stash for.

    I dont know of any alternatives, but you can still use StaSh pip without using the command prompt.
    Simply open launch_stash.py in the editor, long tap the run-Button unitl you are prompted for arguments and then type --command "pip install <package>" (the " are required), which should run pip on start.

    You can also download a .whl manually, then run $STASH_ROOT/lib/stashutils/wheels.py with the path to the wheel as an argument. This will install a .whl file, but wont install any dependencies.

    posted in Pythonista read more
  • bennr01


    I will also say, that running pip install plotly with latest stash caused pip to install all of the plotly folders into site-packages-3, instead of the plotly folder, which totally borked pythonista, and it crashes immediately upon open, even with safemode and pythonista3://. could possibly be my fault for hitting ctrl-z during the process.

    so... don't do that

    There should be a fix in the dev branch of the main repo, or did the fix not work?

    @JonB said:

    I finally got around to trying this on the latest stash. @bennr01, it seems the issue is that pip is not detecting doendencies using the whl.

    Thanks for the info, i will take a look at it.
    This line looks interesting: Warning: could not find 'metadata.json', can not detect dependencies!.
    Apparently the .whl-format is a bit more flexible than i tought...

    posted in Pythonista read more
  • bennr01

    @gary.yang What exactly is not working? Do you get an error message or does it install something in a wrong way? There is a known bug where all subpackages are installed in site-packages-3 instead of their parent package (see here for details).

    posted in Pythonista read more
  • bennr01


    On the phone I still get a fsi, man, patches in stash_extensions that are empty... bin is also empty.

    Do not worry about these folders. They are meant for extensions and are empty by default. In fact, stash_extensions/bin/ is the only one of these folders which is actively used (pip installs commands here).

    I'ts an example I found in a tutorial and I have replaced username and token for my own when I run it.

    I just tested this example on both py2 and py3 and it seems to work (I get some warnings that plotly.graph_objs.Data is deprecated and also an error message that there is no account for [username] (obviously), but it imported and executed fine). I had to install decorator and retrying and also restart pythonista a few times.

    This generated the following traceback:

    Have you tried restarting pythonista (double tap home, the force-quit the app and start again)? Pythonista caches imports, which sometimes leads to weird issues and old imports. You should always restart pythonista if you installed a package to fix an 'ImportError` (or something related).

    If I run my darksky-app, (that I for sure can have broken myself!) it doesn't seem to get 'core'?

    Same as above (btw, import works fine for me, but i have not tested actual functionality).
    BTW, you should avoid from module import *-style imports, as they may lead to import-related problems. A better import would be from darksky.core import *.
    If you are interested in an explanation: As @JonB said, sys.path is modified when a script is executed. This means that python search for imports in a different order depending on the executed script and your CWD. For example, if you would execute/import darksky/__init__.py from within the site-packages/stash-repository, import core would import stash.core instead of darksky.core. This would lead to problems or unexpected behavior.

    Python 3.6.1

    The py3 version of StaSh is still a bit experimental, so there may be more errors compared to py2. That being said, everything above should work fine (i tested your example on both py2 and py3 and darksky on py2) .

    I did upgrade per instructions of @bennr01 : selfupdate -f bennr01:wheelfix
    DarkSky worked when I installed this before, without the wheelfix-upgrade.

    Is there a core.py-file in site-packages-3/darksky/? If there is, then you are probably experiencing some of the CWD-related problems mentioned above. I can confirm that the no module named 'core' error exists depending on the way you import/launch __init__.py You should either try it with from darksky.core import * instead or try to install and run with py2 (py2 has some different import behaviors and from darkskye import forecast works fine). Also, restart after any changes to files in a site-packages* directory, or your change will not take any effect.

    posted in Pythonista read more
  • bennr01

    Hi @hecate,
    I can confirm that this is currently broken.
    However, there is a workaround (though this was tested using py2, not py3):

    1. fixing your install
    When trying to reproduce this issue, my StaSh install broke, so i assume this is the same for you.

    • delete everything in site-packages-3 (or 2, if you use py2)
    • force-quit pythonista and restart.
    • Run pip uninstall plotly . Pythonista crashed for me during this step. If it does, just repeat this.

    2. install plotly
    Go to site-packages/stash/bin/pip.py and replace in PyPIRepository.install() wheel_priority=True with wheel_priority=False. This line should be somewhere around 1052.
    Then run pip install plotly. If you get an error telling you that plotly is already installed, run pip uninstall plotly. Then repeat.

    Plotly should now be installed. I still got some import errors regarding decorators, but it should now be possible to simply install this package/module.

    So, now the other issues:

    Empty local folders (/bin /fsi /man /patches). Is that normal?

    Depends. If you mean the directory /stash_extensions/bin, then yes. This directory is used for extensions, like external commands installed by pip.
    If you mean directories inside site-packages/stash/, then no.

    PIP: I can upgrade on one ipad but the other. --upgrade is an unrecognized argument.

    In StaSh, there is a pip update command. I am surprised that pip install --upgrade worked.
    Maybe one of your devices uses an old version? If you want to check, try running version. The latest version is 0.7.1.

    It seems like there is a bug in the wheel installation handling. Sorry.

    I found the bug and fixed it, but the fix is not yet in the main StaSh repo. To install the fixed version, simply run selfupdate -f bennr01:wheelfix. Please note that you should you should still remove the wrongly installed directories in site-packages-3. If you delete everything in site-packages-3, then you should also delete site-packages-3/.pypi_packages (e.g. rm $HOME/site-packages-3/.pypi_packages).

    posted in Pythonista read more
Internal error.

Oops! Looks like something went wrong!