From srkunze at mail.de Mon Aug 2 15:43:15 2021 From: srkunze at mail.de (Sven R. Kunze) Date: Mon, 2 Aug 2021 21:43:15 +0200 Subject: argparse: delimiter for argparse list arguments Message-ID: <08101473-e47e-3e1d-f64a-9e2d3b615b4f@mail.de> Hi everyone, maybe, I am missing something here but is it possible to specify a delimiter for list arguments in argparse: https://docs.python.org/3/library/argparse.html Usually, '--' is used to separate two lists (cf. git). Cheers, Sven From drsalists at gmail.com Mon Aug 2 19:49:53 2021 From: drsalists at gmail.com (Dan Stromberg) Date: Mon, 2 Aug 2021 16:49:53 -0700 Subject: argparse: delimiter for argparse list arguments In-Reply-To: <08101473-e47e-3e1d-f64a-9e2d3b615b4f@mail.de> References: <08101473-e47e-3e1d-f64a-9e2d3b615b4f@mail.de> Message-ID: Isn't -- usually used to signal the end of options? On Mon, Aug 2, 2021 at 12:52 PM Sven R. Kunze wrote: > Hi everyone, > > maybe, I am missing something here but is it possible to specify a > delimiter for list arguments in argparse: > > https://docs.python.org/3/library/argparse.html > > Usually, '--' is used to separate two lists (cf. git). > > Cheers, > Sven > > -- > https://mail.python.org/mailman/listinfo/python-list > From brgl at bgdev.pl Tue Aug 3 06:03:47 2021 From: brgl at bgdev.pl (Bartosz Golaszewski) Date: Tue, 3 Aug 2021 12:03:47 +0200 Subject: Defining a Python enum in a C extension - am I doing this right? In-Reply-To: References: Message-ID: On Sat, Jul 31, 2021 at 3:01 PM Bartosz Golaszewski wrote: > > On Fri, Jul 30, 2021 at 2:41 PM Serhiy Storchaka wrote: > > > > 23.07.21 11:20, Bartosz Golaszewski ????: > > > I'm working on a Python C extension and I would like to expose a > > > custom enum (as in: a class inheriting from enum.Enum) that would be > > > entirely defined in C. > > > > I think that it would be much easier to define it in Python, and then > > either import a Python module in your C code, or exec a Python code as a > > string. > > > > You mean: evaluate a string like this: > > ''' > import enum > > class FooBar(enum.Enum): > FOO = 1 > BAR = 2 > BAZ = 3 > ''' > > And then pull in the FooBar type from the resulting dictionary into my > C code? Sounds good actually. I think I'll be able to add the FooBar > type to another type's tp_dict too - because some enums I want to > create will be nested in other classes. > > Bart Just a follow-up: this is how I did it eventually: ``` #include typedef struct { PyObject_HEAD; } dummy_object; PyDoc_STRVAR(dummy_type_doc, "Dummy type in which the enum will be nested."); static PyTypeObject dummy_type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "pycenum.DummyType", .tp_basicsize = sizeof(dummy_object), .tp_flags = Py_TPFLAGS_DEFAULT, .tp_doc = dummy_type_doc, .tp_new = PyType_GenericNew, .tp_dealloc = (destructor)PyObject_Del, }; PyDoc_STRVAR(module_doc, "C extension module defining a class inheriting from enum.Enum."); static PyModuleDef module_def = { PyModuleDef_HEAD_INIT, .m_name = "pycenum", .m_doc = module_doc, .m_size = -1, }; static int add_foobar_enum(PyObject *module) { static const char *foobar_src = "class FooBar(enum.Enum):\n" " FOO = 1\n" " BAR = 2\n" " BAZ = 3\n"; PyObject *main_mod, *main_dict, *enum_mod, *result, *foobar_type; int ret; main_mod = PyImport_AddModule("__main__"); if (!main_mod) return -1; main_dict = PyModule_GetDict(main_mod); if (!main_dict) { Py_DECREF(main_mod); return -1; } enum_mod = PyImport_ImportModule("enum"); if (!enum_mod) { Py_DECREF(main_mod); return -1; } ret = PyDict_SetItemString(main_dict, "enum", enum_mod); Py_DECREF(enum_mod); if (ret) { Py_DECREF(main_mod); return -1; } result = PyRun_String(foobar_src, Py_single_input, main_dict, main_dict); if (!result) { Py_DECREF(main_mod); return -1; } foobar_type = PyDict_GetItemString(main_dict, "FooBar"); if (!foobar_type) { Py_DECREF(main_mod); return -1; } ret = PyDict_SetItemString(dummy_type.tp_dict, "FooBar", foobar_type); Py_DECREF(foobar_type); Py_DECREF(main_mod); if (ret) return -1; PyType_Modified(&dummy_type); return ret; } PyMODINIT_FUNC PyInit_pycenum(void) { PyObject *module; int ret; module = PyModule_Create(&module_def); if (!module) return NULL; ret = PyModule_AddStringConstant(module, "__version__", "0.0.1"); if (ret) { Py_DECREF(module); return NULL; } ret = PyType_Ready(&dummy_type); if (ret) { Py_DECREF(module); return NULL; } ret = add_foobar_enum(module); if (ret) { Py_DECREF(module); return NULL; } Py_INCREF(&dummy_type); ret = PyModule_AddObject(module, "DummyType", (PyObject *)&dummy_type); if (ret) { Py_DECREF(&dummy_type); Py_DECREF(module); return NULL; } return module; } ``` Bart From torriem at gmail.com Tue Aug 3 10:45:33 2021 From: torriem at gmail.com (Michael Torrie) Date: Tue, 3 Aug 2021 08:45:33 -0600 Subject: argparse: delimiter for argparse list arguments In-Reply-To: <08101473-e47e-3e1d-f64a-9e2d3b615b4f@mail.de> References: <08101473-e47e-3e1d-f64a-9e2d3b615b4f@mail.de> Message-ID: <9e0c779f-267d-3fb2-d381-414d2d3c0c31@gmail.com> On 8/2/21 1:43 PM, Sven R. Kunze wrote: > Hi everyone, > > maybe, I am missing something here but is it possible to specify a > delimiter for list arguments in argparse: > > https://docs.python.org/3/library/argparse.html > > Usually, '--' is used to separate two lists (cf. git). I've not seen this syntax in git. Are you referring the the double and triple dot notation git uses? Can you give me an example of how git uses -- as a list separator? Typically -- on a command line means that's the end of the any special switches and anything else, even if it looks like a command-line switch, should not be parsed, and passed straight through as a normal parameter. From pablogsal at gmail.com Tue Aug 3 12:31:09 2021 From: pablogsal at gmail.com (Pablo Galindo Salgado) Date: Tue, 3 Aug 2021 17:31:09 +0100 Subject: [RELEASE] Python 3.10.0rc1 is available Message-ID: Python 3.10.0 is almost ready. This release, 3.10.0rc1, is the penultimate release preview. You can get it here: https://www.python.org/downloads/release/python-3100rc1/ *This is the first release candidate of Python 3.10* This release, **3.10.0rc1**, is the penultimate release preview. Entering the release candidate phase, only reviewed code changes which are clear bug fixes are allowed between this release candidate and the final release. The second candidate and the last planned release preview is currently planned for 2021-09-06 while the official release is planned for 2021-10-04. There will be no ABI changes from this point forward in the 3.10 series and the goal is that there will be as few code changes as possible. *Call to action* Core developers: all eyes on the docs now - Are all your changes properly documented? - Did you notice other changes you know of to have insufficient documentation? Community members We strongly encourage maintainers of third-party Python projects to prepare their projects for 3.10 compatibilities during this phase. As always, report any issues to the Python bug tracker . Please keep in mind that this is a preview release and its use is **not** recommended for production environments. *And now for something completely different* In theoretical physics, quantum chromodynamics (QCD) is the theory of the strong interaction between quarks and gluons, the fundamental particles that make up composite hadrons such as the proton, neutron, and pion. The QCD analog of electric charge is a property called color. Gluons are the force carrier of the theory, just as photons are for the electromagnetic force in quantum electrodynamics. There are three kinds of charge in QCD (as opposed to one in quantum electrodynamics or QED) that are usually referred to as "color charge" by loose analogy to the three kinds of color (red, green and blue) perceived by humans. Other than this nomenclature, the quantum parameter "color" is completely unrelated to the everyday, familiar phenomenon of color. *We hope you enjoy those new releases!* Thanks to all of the many volunteers who help make Python Development and these releases possible! Please consider supporting our efforts by volunteering yourself or through organization contributions to the Python Software Foundation. Regards from cloudy London, Your friendly release team, Pablo Galindo @pablogsal Ned Deily @nad Steve Dower @steve.dower From jon+usenet at unequivocal.eu Tue Aug 3 11:48:52 2021 From: jon+usenet at unequivocal.eu (Jon Ribbens) Date: Tue, 3 Aug 2021 15:48:52 -0000 (UTC) Subject: argparse: delimiter for argparse list arguments References: <08101473-e47e-3e1d-f64a-9e2d3b615b4f@mail.de> <9e0c779f-267d-3fb2-d381-414d2d3c0c31@gmail.com> Message-ID: On 2021-08-03, Michael Torrie wrote: > On 8/2/21 1:43 PM, Sven R. Kunze wrote: >> maybe, I am missing something here but is it possible to specify a >> delimiter for list arguments in argparse: >> >> https://docs.python.org/3/library/argparse.html >> >> Usually, '--' is used to separate two lists (cf. git). > > I've not seen this syntax in git. Are you referring the the double and > triple dot notation git uses? Can you give me an example of how git > uses -- as a list separator? Loads of git commands do this. e.g. commit, diff, log, status, etc. It's not completely unlike what you're describing above, which is already supported automatically by argparse. From roel at roelschroeven.net Tue Aug 3 14:54:28 2021 From: roel at roelschroeven.net (Roel Schroeven) Date: Tue, 3 Aug 2021 20:54:28 +0200 Subject: argparse: delimiter for argparse list arguments In-Reply-To: References: <08101473-e47e-3e1d-f64a-9e2d3b615b4f@mail.de> <9e0c779f-267d-3fb2-d381-414d2d3c0c31@gmail.com> Message-ID: Jon Ribbens via Python-list schreef op 3/08/2021 om 17:48: > On 2021-08-03, Michael Torrie wrote: > > On 8/2/21 1:43 PM, Sven R. Kunze wrote: > >> maybe, I am missing something here but is it possible to specify a > >> delimiter for list arguments in argparse: > >> > >> https://docs.python.org/3/library/argparse.html > >> > >> Usually, '--' is used to separate two lists (cf. git). > > > > I've not seen this syntax in git. Are you referring the the double and > > triple dot notation git uses? Can you give me an example of how git > > uses -- as a list separator? > > Loads of git commands do this. e.g. commit, diff, log, status, etc. > It's not completely unlike what you're describing above, which is > already supported automatically by argparse. Commands like git commit do not use '--' to separate two lists, but as Dan and Sven said to separate options from arguments, even if the arguments start with '-' (like many other programs -- I think this is standard in GNU). If you're 100% certain that none of the filenames start with '-', you can leave out '--' without any change in behavior. Especially when scripting and/or using wildcards it's best always to use that '--' to avoid nasty surprises. $ git commit -m "hello" -- hello.py is exactly the same as $ git commit -m "hello" hello.py It's just that the former is safer to use, because it properly works even in cases like $ git commit -m "hello" -- -hello.py whereas $ git commit -m "hello" -hello.py will likely not do what you expect. As https://git-scm.com/docs/git-commit says: > -- > ? Do not interpret any more arguments as options. -- "The saddest aspect of life right now is that science gathers knowledge faster than society gathers wisdom." -- Isaac Asimov From srkunze at mail.de Tue Aug 3 17:06:11 2021 From: srkunze at mail.de (Sven R. Kunze) Date: Tue, 3 Aug 2021 23:06:11 +0200 Subject: argparse: delimiter for argparse list arguments In-Reply-To: References: <08101473-e47e-3e1d-f64a-9e2d3b615b4f@mail.de> Message-ID: <4c4856e5-8ccc-3f35-48df-630c357d3ede@mail.de> It could be but I've seen them used somewhere else. I wouldn't bikeshed on this yet, as I haven't found a way to do this so far. Let's imagine the following parser: parser.add_argument('things',action='append') parser.add_argument('stuff',action='append') At least from my point of view, I don't any way to separate both lists on this command call: cool-script.py thing1 thing2 stuff1 stuff2 Do I miss something here? Best Sven On 03.08.21 01:49, Dan Stromberg wrote: > > Isn't -- usually used to signal the end of options? > > On Mon, Aug 2, 2021 at 12:52 PM Sven R. Kunze > wrote: > > Hi everyone, > > maybe, I am missing something here but is it possible to specify a > delimiter for list arguments in argparse: > > https://docs.python.org/3/library/argparse.html > > > Usually, '--' is used to separate two lists (cf. git). > > Cheers, > Sven > > -- > https://mail.python.org/mailman/listinfo/python-list > > From rosuav at gmail.com Tue Aug 3 17:20:52 2021 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 4 Aug 2021 07:20:52 +1000 Subject: argparse: delimiter for argparse list arguments In-Reply-To: <4c4856e5-8ccc-3f35-48df-630c357d3ede@mail.de> References: <08101473-e47e-3e1d-f64a-9e2d3b615b4f@mail.de> <4c4856e5-8ccc-3f35-48df-630c357d3ede@mail.de> Message-ID: On Wed, Aug 4, 2021 at 7:07 AM Sven R. Kunze wrote: > > It could be but I've seen them used somewhere else. > > I wouldn't bikeshed on this yet, as I haven't found a way to do this so > far. Let's imagine the following parser: > > parser.add_argument('things',action='append') > parser.add_argument('stuff',action='append') > > At least from my point of view, I don't any way to separate both lists > on this command call: > > > cool-script.py thing1 thing2 stuff1 stuff2 > > > Do I miss something here? > I'd probably design it like this: cool-script.py --things thing1 thing2 --stuff stuff1 stuff2 which argparse already handles. ChrisA From jon+usenet at unequivocal.eu Tue Aug 3 16:55:43 2021 From: jon+usenet at unequivocal.eu (Jon Ribbens) Date: Tue, 3 Aug 2021 20:55:43 -0000 (UTC) Subject: argparse: delimiter for argparse list arguments References: <08101473-e47e-3e1d-f64a-9e2d3b615b4f@mail.de> <9e0c779f-267d-3fb2-d381-414d2d3c0c31@gmail.com> Message-ID: On 2021-08-03, Roel Schroeven wrote: > Jon Ribbens via Python-list schreef op 3/08/2021 om 17:48: >> On 2021-08-03, Michael Torrie wrote: >> > On 8/2/21 1:43 PM, Sven R. Kunze wrote: >> >> maybe, I am missing something here but is it possible to specify a >> >> delimiter for list arguments in argparse: >> >> >> >> https://docs.python.org/3/library/argparse.html >> >> >> >> Usually, '--' is used to separate two lists (cf. git). >> > >> > I've not seen this syntax in git. Are you referring the the double and >> > triple dot notation git uses? Can you give me an example of how git >> > uses -- as a list separator? >> >> Loads of git commands do this. e.g. commit, diff, log, status, etc. >> It's not completely unlike what you're describing above, which is >> already supported automatically by argparse. > > Commands like git commit do not use '--' to separate two lists, but as > Dan and Sven said to separate options from arguments, That is not quite correct. Check out 'git diff' for example - it takes as position arguments zero, one, or two commit hashes followed by zero or more pathnames. You can use '--' to separate these two lists, because of course sometimes a pathname can be indistinguishable from a commit hash. From roel at roelschroeven.net Tue Aug 3 18:49:08 2021 From: roel at roelschroeven.net (Roel Schroeven) Date: Wed, 4 Aug 2021 00:49:08 +0200 Subject: argparse: delimiter for argparse list arguments In-Reply-To: References: <08101473-e47e-3e1d-f64a-9e2d3b615b4f@mail.de> <9e0c779f-267d-3fb2-d381-414d2d3c0c31@gmail.com> Message-ID: Jon Ribbens via Python-list schreef op 3/08/2021 om 22:55: > >> Loads of git commands do this. e.g. commit, diff, log, status, etc. > >> It's not completely unlike what you're describing above, which is > >> already supported automatically by argparse. > > > > Commands like git commit do not use '--' to separate two lists, but as > > Dan and Sven said to separate options from arguments, > > That is not quite correct. Check out 'git diff' for example - it takes > as position arguments zero, one, or two commit hashes followed by zero > or more pathnames. You can use '--' to separate these two lists, > because of course sometimes a pathname can be indistinguishable from > a commit hash. Ah yes, I stand corrected, git diff indeed uses -- to separate two lists (commits and paths). -- "Too often we hold fast to the cliches of our forebears. We subject all facts to a prefabricated set of interpretations. Too often we enjoy the comfort of opinion without the discomfort of thought." -- John F Kennedy From larry.martell at gmail.com Tue Aug 3 21:08:17 2021 From: larry.martell at gmail.com (Larry Martell) Date: Tue, 3 Aug 2021 18:08:17 -0700 Subject: SQLALchemy: update with in clause from kwargs Message-ID: I am trying to write a function that takes kwargs as a param and generates an update statement where the rows to be updated are specified in an in clause. Something like this: def update_by_in(self, **kwargs): filter_group = [] for col in kwargs['query_params']: # obviously this line does not work as col is a string, but this is the intent filter_group.append(col.in_(tuple(kwargs['query_params'][col]))) self._session.query(self.model_class).filter(*filter_group).update(kwargs['values']) self.update_by_in( **{'query_params': {'companyCode': ['A', 'B', 'C']}, 'values': {'portfolioName': 'test'}} ) Is there a way to do this? I think I need to use setattr in building up the filter_group list, but I'm not quite sure how to do it. From python at mrabarnett.plus.com Tue Aug 3 22:19:30 2021 From: python at mrabarnett.plus.com (MRAB) Date: Wed, 4 Aug 2021 03:19:30 +0100 Subject: SQLALchemy: update with in clause from kwargs In-Reply-To: References: Message-ID: <9ffe23b7-8f0d-d88f-9d1b-cdaf6b512be3@mrabarnett.plus.com> On 2021-08-04 02:08, Larry Martell wrote: > I am trying to write a function that takes kwargs as a param and > generates an update statement where the rows to be updated are > specified in an in clause. > > Something like this: > > def update_by_in(self, **kwargs): > filter_group = [] > for col in kwargs['query_params']: > # obviously this line does not work as col is a string, > but this is the intent > filter_group.append(col.in_(tuple(kwargs['query_params'][col]))) > > self._session.query(self.model_class).filter(*filter_group).update(kwargs['values']) > > self.update_by_in( > **{'query_params': {'companyCode': ['A', 'B', 'C']}, > 'values': {'portfolioName': 'test'}} > ) > > Is there a way to do this? I think I need to use setattr in building > up the filter_group list, but I'm not quite sure how to do it. > If it's any help, on this page: https://docs.sqlalchemy.org/en/14/core/metadata.html it has this: # access the column "employee_id": employees.columns.employee_id # or just employees.c.employee_id # via string employees.c['employee_id'] From PythonList at DancesWithMice.info Tue Aug 3 22:25:29 2021 From: PythonList at DancesWithMice.info (dn) Date: Wed, 4 Aug 2021 14:25:29 +1200 Subject: SQLALchemy: update with in clause from kwargs In-Reply-To: References: Message-ID: <9544f2d6-10ea-5ac9-2a29-e4d036655e0c@DancesWithMice.info> On 04/08/2021 13.08, Larry Martell wrote: > I am trying to write a function that takes kwargs as a param and > generates an update statement where the rows to be updated are > specified in an in clause. > > Something like this: > > def update_by_in(self, **kwargs): > filter_group = [] > for col in kwargs['query_params']: > # obviously this line does not work as col is a string, > but this is the intent > filter_group.append(col.in_(tuple(kwargs['query_params'][col]))) > > self._session.query(self.model_class).filter(*filter_group).update(kwargs['values']) > > self.update_by_in( > **{'query_params': {'companyCode': ['A', 'B', 'C']}, > 'values': {'portfolioName': 'test'}} > ) > > Is there a way to do this? I think I need to use setattr in building > up the filter_group list, but I'm not quite sure how to do it. When feeling bamboozled by a problem, particularly when using sophisticated tools such as SQLAlchemy, the trick is often to simplify the problem. Step 1 (using the sample data provided) Write the query on paper - and as constant-values. Step 2 Compare the two input dicts with that requirement. Step 3 Work-out the transformation(s) required... One complexity is that the parameter to update_by_in() is formed by joining two dicts. However, the function later tries to treat them in distinct fashions. Why the join/why not two parameters? companyCode = ['A', 'B', 'C'] values = {'portfolioName': 'test'} leading to: self.update_by_in( companyCode, values ) and: def update_by_in(self, company_code, portfolio_type ): .... As to the core of the question-asked, I'm a little confused (which may be my fuzzy head). Do you want the update(s) - portrayed as a list - like this: [('A', 'test'), ('B', 'test'), ('C', 'test')] like this: [('A', 'portfolioName'), ('B', None), ('C', None)] or only: [('A', 'portfolioName')] You will find a friend in the itertools (PSL) library: import itertools as it list( it.product( companyCode, values.values() ) ) [('A', 'test'), ('B', 'test'), ('C', 'test')] list( it.zip_longest( companyCode, values.values() ) ) [('A', 'test'), ('B', None), ('C', None)] list( zip( companyCode, values ) ) [('A', 'portfolioName')] Now, have we simplified things to the point of being able to more-easily code the update and filter? PS I fear even that step is/those steps are more complicated than needed - but you know your data and schema better than I! Critique: 1 never, never, never(!) use a name which will "shadow" a Python keyword or frequently-used function-name (in this case "values" ) - if you don't confuse Python you will confuse simple-boys like me! Plus, when you come back in six-month's time, does "values" tell you what kind of value it is/holds? 2 Python != C | Java Thus: company_code, portfolio_name Web.Refs: https://www.dictionary.com/browse/bamboozled https://docs.python.org/3/library/itertools.html -- Regards, =dn From sean.dizazzo at gmail.com Tue Aug 3 22:24:41 2021 From: sean.dizazzo at gmail.com (Sean DiZazzo) Date: Tue, 3 Aug 2021 19:24:41 -0700 (PDT) Subject: Defining a Python enum in a C extension - am I doing this right? In-Reply-To: References: Message-ID: <4a5d5824-b47d-4d4c-9cc6-026ddac0808bn@googlegroups.com> On Tuesday, August 3, 2021 at 3:04:19 AM UTC-7, Bartosz Golaszewski wrote: > On Sat, Jul 31, 2021 at 3:01 PM Bartosz Golaszewski wrote: > > > > On Fri, Jul 30, 2021 at 2:41 PM Serhiy Storchaka wrote: > > > > > > 23.07.21 11:20, Bartosz Golaszewski ????: > > > > I'm working on a Python C extension and I would like to expose a > > > > custom enum (as in: a class inheriting from enum.Enum) that would be > > > > entirely defined in C. > > > > > > I think that it would be much easier to define it in Python, and then > > > either import a Python module in your C code, or exec a Python code as a > > > string. > > > > > > > You mean: evaluate a string like this: > > > > ''' > > import enum > > > > class FooBar(enum.Enum): > > FOO = 1 > > BAR = 2 > > BAZ = 3 > > ''' > > > > And then pull in the FooBar type from the resulting dictionary into my > > C code? Sounds good actually. I think I'll be able to add the FooBar > > type to another type's tp_dict too - because some enums I want to > > create will be nested in other classes. > > > > Bart > Just a follow-up: this is how I did it eventually: > > ``` > #include > > typedef struct { > PyObject_HEAD; > } dummy_object; > > PyDoc_STRVAR(dummy_type_doc, "Dummy type in which the enum will be nested."); > > static PyTypeObject dummy_type = { > PyVarObject_HEAD_INIT(NULL, 0) > .tp_name = "pycenum.DummyType", > .tp_basicsize = sizeof(dummy_object), > .tp_flags = Py_TPFLAGS_DEFAULT, > .tp_doc = dummy_type_doc, > .tp_new = PyType_GenericNew, > .tp_dealloc = (destructor)PyObject_Del, > }; > PyDoc_STRVAR(module_doc, > "C extension module defining a class inheriting from enum.Enum."); > > static PyModuleDef module_def = { > PyModuleDef_HEAD_INIT, > .m_name = "pycenum", > .m_doc = module_doc, > .m_size = -1, > }; > static int add_foobar_enum(PyObject *module) > { > static const char *foobar_src = > "class FooBar(enum.Enum):\n" > " FOO = 1\n" > " BAR = 2\n" > " BAZ = 3\n"; > > PyObject *main_mod, *main_dict, *enum_mod, *result, *foobar_type; > int ret; > > main_mod = PyImport_AddModule("__main__"); > if (!main_mod) > return -1; > > main_dict = PyModule_GetDict(main_mod); > if (!main_dict) { > Py_DECREF(main_mod); > return -1; > } > > enum_mod = PyImport_ImportModule("enum"); > if (!enum_mod) { > Py_DECREF(main_mod); > return -1; > } > > ret = PyDict_SetItemString(main_dict, "enum", enum_mod); > Py_DECREF(enum_mod); > if (ret) { > Py_DECREF(main_mod); > return -1; > } > > result = PyRun_String(foobar_src, Py_single_input, > main_dict, main_dict); > if (!result) { > Py_DECREF(main_mod); > return -1; > } > > foobar_type = PyDict_GetItemString(main_dict, "FooBar"); > if (!foobar_type) { > Py_DECREF(main_mod); > return -1; > } > > ret = PyDict_SetItemString(dummy_type.tp_dict, "FooBar", foobar_type); > Py_DECREF(foobar_type); > Py_DECREF(main_mod); > if (ret) > return -1; > > PyType_Modified(&dummy_type); > > return ret; > } > > PyMODINIT_FUNC PyInit_pycenum(void) > { > PyObject *module; > int ret; > > module = PyModule_Create(&module_def); > if (!module) > return NULL; > > ret = PyModule_AddStringConstant(module, "__version__", "0.0.1"); > if (ret) { > Py_DECREF(module); > return NULL; > } > > ret = PyType_Ready(&dummy_type); > if (ret) { > Py_DECREF(module); > return NULL; > } > > ret = add_foobar_enum(module); > if (ret) { > Py_DECREF(module); > return NULL; > } > > Py_INCREF(&dummy_type); > ret = PyModule_AddObject(module, "DummyType", (PyObject *)&dummy_type); > if (ret) { > Py_DECREF(&dummy_type); > Py_DECREF(module); > return NULL; > } > > return module; > } > ``` > > Bart No From pablogsal at gmail.com Wed Aug 4 06:15:46 2021 From: pablogsal at gmail.com (Pablo Galindo Salgado) Date: Wed, 4 Aug 2021 11:15:46 +0100 Subject: [RELEASE] Python 3.10.0rc1 is available In-Reply-To: References: Message-ID: Hi, Unfortunately, due to a problem that I was not aware of caused by https://bugs.python.org/issue44756, the release artifacts for Linux contained a "venv" folder in the "Docs" directory. I have uploaded a new version of the artifacts that fixed this problem and I have corrected this for future releases. If you had any problem building docs with the previous release artifacts for 3.10.0rc1, please try again. Regards from cloudy London, Your friendly release team, Pablo Galindo @pablogsal Ned Deily @nad Steve Dower @steve.dower On Tue, 3 Aug 2021 at 17:31, Pablo Galindo Salgado wrote: > Python 3.10.0 is almost ready. This release, 3.10.0rc1, is the > penultimate release preview. You can get it here: > > https://www.python.org/downloads/release/python-3100rc1/ > > > *This is the first release candidate of Python 3.10* > This release, **3.10.0rc1**, is the penultimate release preview. Entering > the release candidate phase, only reviewed code changes which are > clear bug fixes are allowed between this release candidate and the final > release. The second candidate and the last planned release preview is > currently planned for 2021-09-06 while the official release is planned for > 2021-10-04. > > There will be no ABI changes from this point forward in the 3.10 series > and the goal is that there will be as few code changes as possible. > > *Call to action* > Core developers: all eyes on the docs now > > - Are all your changes properly documented? > - Did you notice other changes you know of to have insufficient > documentation? > > Community members > > We strongly encourage maintainers of third-party Python projects to > prepare their projects for 3.10 compatibilities during this phase. As > always, report any issues to the Python bug tracker > . > Please keep in mind that this is a preview release and its use is **not** > recommended for production environments. > > *And now for something completely different* > > In theoretical physics, quantum chromodynamics (QCD) is the theory of the > strong interaction between quarks and gluons, the fundamental particles > that make up composite hadrons such as the proton, neutron, and pion. The > QCD analog of electric charge is a property called color. Gluons are the > force carrier of the theory, just as photons are for the electromagnetic > force in quantum electrodynamics. There are three kinds of charge in QCD > (as opposed to one in quantum electrodynamics or QED) that are usually > referred to as "color charge" by loose analogy to the three kinds of color > (red, green and blue) perceived by humans. Other than this nomenclature, > the quantum parameter "color" is completely unrelated to the everyday, > familiar phenomenon of color. > > > *We hope you enjoy those new releases!* > Thanks to all of the many volunteers who help make Python Development and > these releases possible! Please consider supporting our efforts by > volunteering yourself or through organization contributions to the Python > Software Foundation. > > Regards from cloudy London, > > Your friendly release team, > Pablo Galindo @pablogsal > Ned Deily @nad > Steve Dower @steve.dower > From larry.martell at gmail.com Wed Aug 4 15:36:29 2021 From: larry.martell at gmail.com (Larry Martell) Date: Wed, 4 Aug 2021 12:36:29 -0700 Subject: SQLALchemy: update with in clause from kwargs In-Reply-To: <9544f2d6-10ea-5ac9-2a29-e4d036655e0c@DancesWithMice.info> References: <9544f2d6-10ea-5ac9-2a29-e4d036655e0c@DancesWithMice.info> Message-ID: On Tue, Aug 3, 2021 at 7:26 PM dn via Python-list wrote: > > On 04/08/2021 13.08, Larry Martell wrote: > > I am trying to write a function that takes kwargs as a param and > > generates an update statement where the rows to be updated are > > specified in an in clause. > > > > Something like this: > > > > def update_by_in(self, **kwargs): > > filter_group = [] > > for col in kwargs['query_params']: > > # obviously this line does not work as col is a string, > > but this is the intent > > filter_group.append(col.in_(tuple(kwargs['query_params'][col]))) > > > > self._session.query(self.model_class).filter(*filter_group).update(kwargs['values']) > > > > self.update_by_in( > > **{'query_params': {'companyCode': ['A', 'B', 'C']}, > > 'values': {'portfolioName': 'test'}} > > ) > > > > Is there a way to do this? I think I need to use setattr in building > > up the filter_group list, but I'm not quite sure how to do it. > > > When feeling bamboozled by a problem, particularly when using > sophisticated tools such as SQLAlchemy, the trick is often to simplify > the problem. > > Step 1 (using the sample data provided) > Write the query on paper - and as constant-values. > > Step 2 > Compare the two input dicts with that requirement. > > Step 3 > Work-out the transformation(s) required... > > > One complexity is that the parameter to update_by_in() is formed by > joining two dicts. However, the function later tries to treat them in > distinct fashions. Why the join/why not two parameters? > > companyCode = ['A', 'B', 'C'] > values = {'portfolioName': 'test'} > > leading to: > > self.update_by_in( companyCode, values ) > > and: > > def update_by_in(self, company_code, portfolio_type ): > .... > > > As to the core of the question-asked, I'm a little confused (which may > be my fuzzy head). Do you want the update(s) - portrayed as a list - > like this: > > [('A', 'test'), ('B', 'test'), ('C', 'test')] > > like this: > > [('A', 'portfolioName'), ('B', None), ('C', None)] > > or only: > > [('A', 'portfolioName')] > > > You will find a friend in the itertools (PSL) library: > > import itertools as it > > list( it.product( companyCode, values.values() ) ) > [('A', 'test'), ('B', 'test'), ('C', 'test')] > > list( it.zip_longest( companyCode, values.values() ) ) > [('A', 'test'), ('B', None), ('C', None)] > > list( zip( companyCode, values ) ) > [('A', 'portfolioName')] > > > Now, have we simplified things to the point of being able to more-easily > code the update and filter? I appreciate the reply, but it does not address my issue, which was how to get at the column object. Turned out that was simple enough: for col in kwargs['query_params']: attr = getattr(self.model_class, col) filter_group.append(attr.in_(tuple(kwargs['query_params'][col]))) Unfortunately that is causing something to change the query_params, as filter group ends up like: print(type(filter_group[0])) print(filter_group[0]) dbo."Portfolio"."companyCode" IN (:companyCode_1, :companyCode_2, :companyCode_3) Which then fails with: sqlalchemy.orm.evaluator.UnevaluatableError: Cannot evaluate clauselist with operator This has now become more of a sqlalchemy question than a python one. From javi.xeneize at gmail.com Wed Aug 4 17:26:45 2021 From: javi.xeneize at gmail.com (Javi D R) Date: Wed, 4 Aug 2021 22:26:45 +0100 Subject: Tracing in a Flask application Message-ID: Hi I would like to do some tracing in a flask. I have been able to trace request in plain python requests using sys.settrace(), but this doesnt work with Flask. Moreover, what i want to trace is in a flask application, when an endpoint is called, what was the request, which parts of the code was executed (i think i can still do it with settrace) and what is the response sent by the application Can you help me to understand which services i can use to do this? Thanks From jfong at ms4.hinet.net Thu Aug 5 05:40:30 2021 From: jfong at ms4.hinet.net (Jach Feng) Date: Thu, 5 Aug 2021 02:40:30 -0700 (PDT) Subject: Ask for help on using re Message-ID: <904b3a0e-9e0f-401a-8bb0-cf14de5a8a85n@googlegroups.com> I want to distinguish between numbers with/without a dot attached: >>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' >>> re.compile(r'ch \d{1,}[.]').findall(text) ['ch 1.', 'ch 23.'] >>> re.compile(r'ch \d{1,}[^.]').findall(text) ['ch 23', 'ch 4 ', 'ch 56 '] I can guess why the 'ch 23' appears in the second list. But how to get rid of it? --Jach From nddtwentyone at gmail.com Thu Aug 5 06:36:39 2021 From: nddtwentyone at gmail.com (Neil) Date: 05 Aug 2021 10:36:39 GMT Subject: Ask for help on using re References: <904b3a0e-9e0f-401a-8bb0-cf14de5a8a85n@googlegroups.com> Message-ID: <610bbf35$0$695$14726298@news.sunsite.dk> Jach Feng wrote: > I want to distinguish between numbers with/without a dot attached: > >>>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' >>>> re.compile(r'ch \d{1,}[.]').findall(text) > ['ch 1.', 'ch 23.'] >>>> re.compile(r'ch \d{1,}[^.]').findall(text) > ['ch 23', 'ch 4 ', 'ch 56 '] > > I can guess why the 'ch 23' appears in the second list. But how to get rid of it? > > --Jach Does >>> re.findall(r'ch\s+\d+(?![.\d])',text) do what you want? This matches "ch", then any nonzero number of whitespaces, then any nonzero number of digits, provided this is not followed by a dot or another digit. From jfong at ms4.hinet.net Thu Aug 5 07:13:05 2021 From: jfong at ms4.hinet.net (Jach Feng) Date: Thu, 5 Aug 2021 04:13:05 -0700 (PDT) Subject: Ask for help on using re In-Reply-To: <610bbf35$0$695$14726298@news.sunsite.dk> References: <904b3a0e-9e0f-401a-8bb0-cf14de5a8a85n@googlegroups.com> <610bbf35$0$695$14726298@news.sunsite.dk> Message-ID: <838626e9-8354-4ce3-8c79-6fdeeb3c91f6n@googlegroups.com> Neil ? 2021?8?5? ?????6:36:58 [UTC+8] ?????? > Jach Feng wrote: > > I want to distinguish between numbers with/without a dot attached: > > > >>>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' > >>>> re.compile(r'ch \d{1,}[.]').findall(text) > > ['ch 1.', 'ch 23.'] > >>>> re.compile(r'ch \d{1,}[^.]').findall(text) > > ['ch 23', 'ch 4 ', 'ch 56 '] > > > > I can guess why the 'ch 23' appears in the second list. But how to get rid of it? > > > > --Jach > Does > > >>> re.findall(r'ch\s+\d+(?![.\d])',text) > > do what you want? This matches "ch", then any nonzero number of > whitespaces, then any nonzero number of digits, provided this is not > followed by a dot or another digit. Yes, the result is what I want. Thank you, Neil! The solution is more complex than I expect. Have to digest it:-) --Jach From robin at reportlab.com Thu Aug 5 08:50:47 2021 From: robin at reportlab.com (Robin Becker) Date: Thu, 5 Aug 2021 13:50:47 +0100 Subject: error from pypa build Message-ID: <2142414c-f095-480a-5c56-6ce7234735f7@everest.reportlab.co.uk> I'm building a pure python wheel in a python3.9 virtualenv. If I use python setup.py bdist_wheel I do get a wheel named rlextra-3.6.0-py3-none-any.whl I'm trying out building a modern python 3 only wheel so I followed instructions here https://packaging.python.org/tutorials/packaging-projects/#creating-the-package-files and see the error below which is not very informative. Any ideas of what's wrong? I still get the error even after upgrading pip so I don't think that is the problem. > (.py39) user at pc:~/devel/reportlab/REPOS/rlextra > $ pip install build > Collecting build > Downloading build-0.5.1-py2.py3-none-any.whl (15 kB) > Collecting pep517>=0.9.1 > .......... > Installing collected packages: tomli, pyparsing, toml, pep517, packaging, build > Successfully installed build-0.5.1 packaging-21.0 pep517-0.11.0 pyparsing-2.4.7 toml-0.10.2 tomli-1.2.0 > WARNING: You are using pip version 21.1.3; however, version 21.2.2 is available. > You should consider upgrading via the '/home/user/devel/reportlab/.py39/bin/python39 -m pip install --upgrade pip' command. > (.py39) user at pc:~/devel/reportlab/REPOS/rlextra > $ ls > build dist docs examples LICENSE.txt README.txt setup.cfg setup.py src tests tmp > (.py39) user at pc:~/devel/reportlab/REPOS/rlextra > $ python -m build --wheel > Traceback (most recent call last): > File "/home/user/devel/reportlab/.py39/lib/python3.9/site-packages/build/__main__.py", line 302, in main > build_call(args.srcdir, outdir, distributions, config_settings, not args.no_isolation, args.skip_dependency_check) > File "/home/user/devel/reportlab/.py39/lib/python3.9/site-packages/build/__main__.py", line 145, in build_package > _build(isolation, builder, outdir, distribution, config_settings, skip_dependency_check) > File "/home/user/devel/reportlab/.py39/lib/python3.9/site-packages/build/__main__.py", line 101, in _build > return _build_in_isolated_env(builder, outdir, distribution, config_settings) > File "/home/user/devel/reportlab/.py39/lib/python3.9/site-packages/build/__main__.py", line 77, in _build_in_isolated_env > with IsolatedEnvBuilder() as env: > File "/home/user/devel/reportlab/.py39/lib/python3.9/site-packages/build/env.py", line 92, in __enter__ > executable, scripts_dir = _create_isolated_env_venv(self._path) > File "/home/user/devel/reportlab/.py39/lib/python3.9/site-packages/build/env.py", line 221, in _create_isolated_env_venv > pip_distribution = next(iter(metadata.distributions(name='pip', path=[purelib]))) > StopIteration > > ERROR > (.py39) user at pc:~/devel/reportlab/REPOS/rlextra thanks for any assistance -- Robin Becker From pkpearson at nowhere.invalid Thu Aug 5 11:00:15 2021 From: pkpearson at nowhere.invalid (Peter Pearson) Date: 5 Aug 2021 15:00:15 GMT Subject: Ask for help on using re References: <904b3a0e-9e0f-401a-8bb0-cf14de5a8a85n@googlegroups.com> Message-ID: On Thu, 5 Aug 2021 02:40:30 -0700 (PDT), Jach Feng wrote: I want to distinguish between numbers with/without a dot attached: >>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' >>> re.compile(r'ch \d{1,}[.]').findall(text) ['ch 1.', 'ch 23.'] >>> re.compile(r'ch \d{1,}[^.]').findall(text) ['ch 23', 'ch 4 ', 'ch 56 '] I can guess why the 'ch 23' appears in the second list. But how to get rid of it? >>> re.findall(r'ch \d+[^.0-9]', "ch 1. is ch 23. is ch 4 is ch 56 is ") ['ch 4 ', 'ch 56 '] -- To email me, substitute nowhere->runbox, invalid->com. From ast at invalid Thu Aug 5 11:11:58 2021 From: ast at invalid (ast) Date: Thu, 5 Aug 2021 17:11:58 +0200 Subject: Ask for help on using re In-Reply-To: <904b3a0e-9e0f-401a-8bb0-cf14de5a8a85n@googlegroups.com> References: <904b3a0e-9e0f-401a-8bb0-cf14de5a8a85n@googlegroups.com> Message-ID: <610bffbe$0$6185$426a34cc@news.free.fr> Le 05/08/2021 ? 11:40, Jach Feng a ?crit?: > I want to distinguish between numbers with/without a dot attached: > >>>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' >>>> re.compile(r'ch \d{1,}[.]').findall(text) > ['ch 1.', 'ch 23.'] >>>> re.compile(r'ch \d{1,}[^.]').findall(text) > ['ch 23', 'ch 4 ', 'ch 56 '] > > I can guess why the 'ch 23' appears in the second list. But how to get rid of it? > > --Jach > >>> import re >>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' >>> re.findall(r'ch \d+\.', text) ['ch 1.', 'ch 23.'] >>> re.findall(r'ch \d+(?!\.)', text) # (?!\.) for negated look ahead ['ch 2', 'ch 4', 'ch 56'] From ast at invalid Thu Aug 5 11:21:42 2021 From: ast at invalid (ast) Date: Thu, 5 Aug 2021 17:21:42 +0200 Subject: Ask for help on using re In-Reply-To: <610bffbe$0$6185$426a34cc@news.free.fr> References: <904b3a0e-9e0f-401a-8bb0-cf14de5a8a85n@googlegroups.com> <610bffbe$0$6185$426a34cc@news.free.fr> Message-ID: <610c0206$0$23960$426a34cc@news.free.fr> Le 05/08/2021 ? 17:11, ast a ?crit?: > Le 05/08/2021 ? 11:40, Jach Feng a ?crit?: >> I want to distinguish between numbers with/without a dot attached: >> >>>>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' >>>>> re.compile(r'ch \d{1,}[.]').findall(text) >> ['ch 1.', 'ch 23.'] >>>>> re.compile(r'ch \d{1,}[^.]').findall(text) >> ['ch 23', 'ch 4 ', 'ch 56 '] >> >> I can guess why the 'ch 23' appears in the second list. But how to get >> rid of it? >> >> --Jach >> > > >>> import re > > >>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' > > >>> re.findall(r'ch \d+\.', text) > ['ch 1.', 'ch 23.'] > > >>> re.findall(r'ch \d+(?!\.)', text)?? # (?!\.) for negated look ahead > ['ch 2', 'ch 4', 'ch 56'] ops ch2 is found. Wrong From ast at invalid Thu Aug 5 11:28:57 2021 From: ast at invalid (ast) Date: Thu, 5 Aug 2021 17:28:57 +0200 Subject: Ask for help on using re In-Reply-To: <610bffbe$0$6185$426a34cc@news.free.fr> References: <904b3a0e-9e0f-401a-8bb0-cf14de5a8a85n@googlegroups.com> <610bffbe$0$6185$426a34cc@news.free.fr> Message-ID: <610c03b9$0$6455$426a34cc@news.free.fr> Le 05/08/2021 ? 17:11, ast a ?crit?: > Le 05/08/2021 ? 11:40, Jach Feng a ?crit?: >> I want to distinguish between numbers with/without a dot attached: >> >>>>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' >>>>> re.compile(r'ch \d{1,}[.]').findall(text) >> ['ch 1.', 'ch 23.'] >>>>> re.compile(r'ch \d{1,}[^.]').findall(text) >> ['ch 23', 'ch 4 ', 'ch 56 '] >> >> I can guess why the 'ch 23' appears in the second list. But how to get >> rid of it? >> >> --Jach >> > > >>> import re > > >>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' > > >>> re.findall(r'ch \d+\.', text) > ['ch 1.', 'ch 23.'] > > >>> re.findall(r'ch \d+(?!\.)', text)?? # (?!\.) for negated look ahead > ['ch 2', 'ch 4', 'ch 56'] import regex # regex is more powerful that re >>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' >>> regex.findall(r'ch \d++(?!\.)', text) ['ch 4', 'ch 56'] ## ++ means "possessive", no backtrack is allowed From surethaweweje at gmail.com Fri Aug 6 11:50:02 2021 From: surethaweweje at gmail.com (Suretha Weweje) Date: Fri, 6 Aug 2021 17:50:02 +0200 Subject: =?UTF-8?Q?Flask_=E2=80=93_how_to_write_csv_file_=26_save_using_prefill?= =?UTF-8?Q?ed_value_of_the_filename_=28response=2Eheaders=5B=22Content=2DDisposit?= =?UTF-8?Q?ion=22=5D=3D=22attachment=3B_filename=3Dxxx=22=29?= Message-ID: I am trying to upload a CSV file with flask, read and process one line at a time while iterating through all rows of the file and write the results back to a new CSV file. My python script produces the correct results on its own, but I am not able to get the same results when using Flask. I am new to flask. The CSV file that I want to work on has different row lengths and each row contains the pair of column names(headers) and cell values for that row. ***Short example of the CSV file content** I am trying to upload with flask* 3012,"COMPANY NAME",3015,"LIVE",3020,916301,3022,"LB45",9999 4000,"92001",4018,"FORM5",4022,"A",4025,2017,4030,"SMITH",4040,"ANN",4060,?C5,9999 4000,"92002",4018,"FORM5",4022,"A",4025,2017,4030,"BROWN",4040,"JOE",4075,89500,9999 ***The expected results*** 3012 3015 3020 3022 4000 4018 4022 4025 4030 4040 4060 4075 COMP NAME "LIVE" 916301 "LB45" "92001" "FORM5" "A" 2017 "SMITH" "ANN " C5 "92002" "FORM5" "A" 2017 "BROWN" "JOE" 89500 *** This is my code so far *** from flask import Flask*, *make_response*, **request* import io import csv *app *= Flask(__name__) def transform(*text_file_contents*): *output *= [] *strip9999 *= [] *the_headers *= [] *headers_new *= [] *num_lines *= *0 **new *= *text_file_contents*.replace("9999"*, *"") *csv_reader *= csv.reader(*new*) for *line *in *csv_reader*: *dictionary *= str(*line*) *strip9999*.append(*dictionary*) for *row *in *strip9999*: *it *= iter(*row*) *res_dct *= dict(zip(*it**, **it*)) *output*.append(*res_dct*) for *key *in *res_dct*: *f_name *= *key the_headers*.append(*f_name*) *the_headers *= list(set(sorted(*the_headers*))) *headers_new *= sorted(*the_headers*) *mywriter = csv.DictWriter('results.csv', fieldnames=headers_new)* *mywriter*.writeheader() for *data *in *output*: *mywriter*.writerow(*data*) *num_lines *+= *1 *return *data *@*app*.route('/') def form(): return """

Select File To Convert

""" @*app*.route('/transform'*, *methods=["POST"]) def transform_file(): *f *= *request*.files['data_file'] if not *f*: return "No file" *stream *= io.StringIO(*f*.stream.read().decode("UTF8")*, *newline=None) csv_input = csv.reader(*stream*) *stream*.seek(*0*) *result = transform(stream.read())* *response *= make_response(*result*) *response*.headers["Content-Disposition"] = "attachment; filename=result.csv" return *response *if __name__ == "__main__": *app*.run(debug=True) ***The following TypeError**:* *argument 1 must have a "write" method *is displayed noting these two problems: - result = transform(stream.read()) and - mywriter = csv.DictWriter('results.csv', fieldnames=headers_new) I am not sure if the problem might be with mywriter because the original Python script below work fine as with open('results.csv', 'x', newline='') as new_file: mywriter = csv.DictWriter(new_file, fieldnames=headers_new) mywriter.writeheader() whereas in Flask I am not sure how to link data written using the function to **response.headers["Content-Disposition"] = "attachment; filename=result.csv"** From python at mrabarnett.plus.com Fri Aug 6 12:13:54 2021 From: python at mrabarnett.plus.com (MRAB) Date: Fri, 6 Aug 2021 17:13:54 +0100 Subject: =?UTF-8?Q?Re=3a_Flask_=e2=80=93_how_to_write_csv_file_=26_save_usin?= =?UTF-8?Q?g_prefilled_value_of_the_filename_=28response=2eheaders=5b=22Cont?= =?UTF-8?B?ZW50LURpc3Bvc2l0aW9uIl09ImF0dGFjaG1lbnQ7IGZpbGVuYW1lPXh4eCIp?= In-Reply-To: References: Message-ID: On 2021-08-06 16:50, Suretha Weweje wrote: > I am trying to upload a CSV file with flask, read and process one line at a > time while iterating through all rows of the file and write the results > back to a new CSV file. My python script produces the correct results on > its own, but I am not able to get the same results when using Flask. I am > new to flask. > [snip] > > csv_reader = csv.reader(new) > [snip] > > *mywriter = csv.DictWriter('results.csv', fieldnames=headers_new)* [snip] The problem has nothing to do with Flask. 'csv.reader' and 'csv.DictWriter' expect a file object, but you're passing them strings. From storchaka at gmail.com Fri Aug 6 03:45:38 2021 From: storchaka at gmail.com (Serhiy Storchaka) Date: Fri, 6 Aug 2021 10:45:38 +0300 Subject: Defining a Python enum in a C extension - am I doing this right? In-Reply-To: References: Message-ID: 03.08.21 13:03, Bartosz Golaszewski ????: > Just a follow-up: this is how I did it eventually: I think it can be simpler. 1. No need to create the __main__ module. You can just create a dict. If some attributes are required (e.g. __name__) it is easy to set them in the Python code (__name__ = 'pycenum'). 2. No need to import the enum module in the C code. It is easier to do it in the Python code. 3. Can you define your DummyType in the Python code instead of the C code? Even if you need to create in the C code, it may be better to define your enum class inside a dummy DummyType. It will set correct __qualname__ of the enum class: __name__ = 'pycenum' import enum class DummyType: class FooBar(enum.Enum): ... 4. Did you consider idea of making DummyType a heap-allocated type? It may be easy to create new type with PyType_FromModuleAndSpec(), and it is more stable API, and the type is not immutable, so it is easy to add new attributes with PyObject_SetAttrString(). From ast at invalid Fri Aug 6 05:18:27 2021 From: ast at invalid (ast) Date: Fri, 6 Aug 2021 11:18:27 +0200 Subject: Ask for help on using re In-Reply-To: References: <904b3a0e-9e0f-401a-8bb0-cf14de5a8a85n@googlegroups.com> <610bffbe$0$6185$426a34cc@news.free.fr> <610c03b9$0$6455$426a34cc@news.free.fr> Message-ID: <610cfe63$0$32528$426a74cc@news.free.fr> Le 06/08/2021 ? 02:57, Jach Feng a ?crit?: > ast ? 2021?8?5? ?????11:29:15 [UTC+8] ?????? >> Le 05/08/2021 ? 17:11, ast a ?crit : >>> Le 05/08/2021 ? 11:40, Jach Feng a ?crit : >> import regex >> >> # regex is more powerful that re >>>>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' >>>>> regex.findall(r'ch \d++(?!\.)', text) >> >> ['ch 4', 'ch 56'] >> >> ## ++ means "possessive", no backtrack is allowed > Can someone explain how the difference appear? I just can't figure it out:-( > +, *, ? are greedy, means they try to catch as many characters as possible. But if the whole match doesn't work, they release some characters once at a time and try the whole match again. That's backtrack. With ++, backtrack is not allowed. This works with module regex and it is not implemented in module re with string = "ch 23." and pattern = r"ch \d+\." At first trial \d+ catch 23 but whole match will fail because next character is . and . is not allowed (\.) A backtrack happens: \d+ catch only 2 and the whole match is successful because the next char 3 is not . But this is not what we want. with ++, no backtrack, so no match "ch 23." is rejected this is what we wanted Using re only, the best way is probably re.findall(r"ch \d+(?![.0-9])", text) ['ch 4', 'ch 56'] From jbrandom at example.com Thu Aug 5 13:35:08 2021 From: jbrandom at example.com (Jack Brandom) Date: Thu, 05 Aug 2021 14:35:08 -0300 Subject: on slices, negative indices, which are the equivalent procedures? Message-ID: <86sfznhk1f.fsf@example.com> The FAQ at https://docs.python.org/3/faq/programming.html#what-s-a-negative-index makes me think that I can always replace negative indices with positive ones --- even in slices, although the FAQ seems not to say anything about slices. With slices, it doesn't seem to always work. For instance, I can reverse a "Jack" this way: >>> s = "Jack Brandom" >>> s[3 : -13 : -1] 'kcaJ' I have no idea how to replace that -13 with a positive index. Is it possible at all? But this example gives me the idea that perhaps each slice is equivalent to a certain loop (which I could write in a procedure). So I'm looking for these procedures. If I can have the procedures in mind, I think I will be able to undersand slices without getting surprised. Do you have these procedures from the top of your mind? While I haven't given up yet, I am not getting too close. Thank you! From michael.stemper at gmail.com Thu Aug 5 15:12:48 2021 From: michael.stemper at gmail.com (Michael F. Stemper) Date: Thu, 5 Aug 2021 14:12:48 -0500 Subject: on slices, negative indices, which are the equivalent procedures? In-Reply-To: <86sfznhk1f.fsf@example.com> References: <86sfznhk1f.fsf@example.com> Message-ID: On 05/08/2021 12.35, Jack Brandom wrote: > The FAQ at > > https://docs.python.org/3/faq/programming.html#what-s-a-negative-index > > makes me think that I can always replace negative indices with positive > ones --- even in slices, although the FAQ seems not to say anything > about slices. > > With slices, it doesn't seem to always work. For instance, I can > reverse a "Jack" this way: > >>>> s = "Jack Brandom" >>>> s[3 : -13 : -1] > 'kcaJ' > > I have no idea how to replace that -13 with a positive index. Is it > possible at all? I don't think so, because the second number (in this case -13) is the index before which you stop. For example: >>> s 'Jack Brandom' >>> s[3:0:-1] 'kca' >>> s[3:1:-1] 'kc' >>> However, since you want to go through item 0 in the original string, you don't need a number there at all: >>> s[3::-1] 'kcaJ' >>> Or, it you want to be more explicit, you could separately grab the substring and then reverse it: >>> s[:4][::-1] 'kcaJ' >>> Does any of this help? -- Michael F. Stemper If it isn't running programs and it isn't fusing atoms, it's just bending space. From jbrandom at example.com Thu Aug 5 20:00:08 2021 From: jbrandom at example.com (Jack Brandom) Date: Thu, 05 Aug 2021 21:00:08 -0300 Subject: on slices, negative indices, which are the equivalent procedures? References: <86sfznhk1f.fsf@example.com> Message-ID: <86czqre92v.fsf@example.com> "Michael F. Stemper" writes: > On 05/08/2021 12.35, Jack Brandom wrote: >> The FAQ at >> https://docs.python.org/3/faq/programming.html#what-s-a-negative-index >> makes me think that I can always replace negative indices with >> positive >> ones --- even in slices, although the FAQ seems not to say anything >> about slices. >> With slices, it doesn't seem to always work. For instance, I can >> reverse a "Jack" this way: >> >>>>> s = "Jack Brandom" >>>>> s[3 : -13 : -1] >> 'kcaJ' >> I have no idea how to replace that -13 with a positive index. Is it >> possible at all? > > I don't think so, because the second number (in this case -13) is the > index before which you stop. So, can you write a procedure that implements these rules? It seems that I'd begin at position 3 (that's "k" which I save somewhere), then I subtract 1 from 3, getting 2 (that's "c", which I save somewhere), then I subtract 1 from 2, getting 1 (that's "a", ...), then I subtract 1 from 1, getting 0 (that's J, ...), so I got "kcaJ" but my counter is 0 not -13, which was my stopping point. So it doesn't work as I'm currently thinking --- and my attempt to write a procedure would not work. There must be a procedure that mimics this, of course. I haven't understood the rules enough yet. > For example: > >>>> s > 'Jack Brandom' >>>> s[3:0:-1] > 'kca' Okay, so we begin at 3 (which is "k"), then we go towards the beginning of the string because of step = -1. This would work with my iteration attempted above --- I'd subtract 1 from 3, then from 2, then from 1 and I'd stop as soon as I reach 0, so I wouldn't collect the J, as desired. (I could write, therefore, such procedure for this case.) >>>> s[3:1:-1] > 'kc' Okay. > However, since you want to go through item 0 in the original string, > you don't need a number there at all: > >>>> s[3::-1] > 'kcaJ' Thanks for mentioning this. > Or, it you want to be more explicit, you could separately grab the > substring and then reverse it: > >>>> s[:4][::-1] > 'kcaJ' This is interesting. It's a way to break the problem into smaller steps. So [::-1] always reverses the iterable. > Does any of this help? It does. Thank you. But my main objective is to imitate the rules of slicing so that I can understand it. In other words, I'd like to write myself a procedure --- say mySlice --- that takes an iterable and three integers (say beg, end, step) and be able to produce precisely iterable[beg : end : step] without using this syntax. This would give me the feeling that I really know how it works. (Because I simulated it.) Ignoring the type of the iterable for now, I could begin with something like this: --8<---------------cut here---------------start------------->8--- def mySlice(it, beg, end, step = 1): ret = [] cur = beg if step > 0: while cur < end: ret.append(it[cur]) cur += 1 return ret if step < 0: return "not sure yet" --8<---------------cut here---------------end--------------->8--- >>> "Jack Brandom"[0:4:1] 'Jack' >>> mySlice("Jack Brandom", 0, 4, 1) ['J', 'a', 'c', 'k'] That's the spirit. I can say I know the behavior because I can imitate it perfectly. But there seems to be various combinations of positive and negative in the indices that confuses my mind pretty easily. I think I need to break this down into cases and understand all the possible behaviors. For now, I think I can say that if the step is positive, then it goes from the first indice to the second. (It moves in that direction.) If the step is negative, then it goes from the first indice to the second but the second must be smaller than the first. (But I'm assuming here all indices are positive and only the step can switch sign.) (This thing is looking too confusing. I must be missing some simple rule.) From jfong at ms4.hinet.net Thu Aug 5 20:57:14 2021 From: jfong at ms4.hinet.net (Jach Feng) Date: Thu, 5 Aug 2021 17:57:14 -0700 (PDT) Subject: Ask for help on using re In-Reply-To: <610c03b9$0$6455$426a34cc@news.free.fr> References: <904b3a0e-9e0f-401a-8bb0-cf14de5a8a85n@googlegroups.com> <610bffbe$0$6185$426a34cc@news.free.fr> <610c03b9$0$6455$426a34cc@news.free.fr> Message-ID: ast ? 2021?8?5? ?????11:29:15 [UTC+8] ?????? > Le 05/08/2021 ? 17:11, ast a ?crit : > > Le 05/08/2021 ? 11:40, Jach Feng a ?crit : > >> I want to distinguish between numbers with/without a dot attached: > >> > >>>>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' > >>>>> re.compile(r'ch \d{1,}[.]').findall(text) > >> ['ch 1.', 'ch 23.'] > >>>>> re.compile(r'ch \d{1,}[^.]').findall(text) > >> ['ch 23', 'ch 4 ', 'ch 56 '] > >> > >> I can guess why the 'ch 23' appears in the second list. But how to get > >> rid of it? > >> > >> --Jach > >> > > > > >>> import re > > > > >>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' > > > > >>> re.findall(r'ch \d+\.', text) > > ['ch 1.', 'ch 23.'] > > > > >>> re.findall(r'ch \d+(?!\.)', text) # (?!\.) for negated look ahead > > ['ch 2', 'ch 4', 'ch 56'] > import regex > > # regex is more powerful that re > >>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' > >>> regex.findall(r'ch \d++(?!\.)', text) > > ['ch 4', 'ch 56'] > > ## ++ means "possessive", no backtrack is allowed Can someone explain how the difference appear? I just can't figure it out:-( >>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' >>> re.compile(r'ch \d+[^.]').findall(text) ['ch 23', 'ch 4 ', 'ch 56 '] >>> re.compile(r'ch \d+[^.0-9]').findall(text) ['ch 4 ', 'ch 56 '] --Jach From jfong at ms4.hinet.net Thu Aug 5 23:05:29 2021 From: jfong at ms4.hinet.net (Jach Feng) Date: Thu, 5 Aug 2021 20:05:29 -0700 (PDT) Subject: on slices, negative indices, which are the equivalent procedures? In-Reply-To: <86czqre92v.fsf@example.com> References: <86sfznhk1f.fsf@example.com> <86czqre92v.fsf@example.com> Message-ID: <00316df8-b5e3-4240-8e8d-6d1439a5356bn@googlegroups.com> > >>>>> s = "Jack Brandom" > >>>>> s[3 : -13 : -1] > >> 'kcaJ' > >> I have no idea how to replace that -13 with a positive index. Is it > >> possible at all? That's not possible because a positive index is relative to the leftmost item 0 Below is some rules of slice usage which I collected sometimes ago. ----- slice s[i:j:k] The result is from start index i to stop index j (excluded) in step k (default is 1). i, j, k can be positive or negative. For example: s = [1, 2, 3, 4, 5] 1. Positive index is relative to the leftmost item (0), negative index is relative to the rightmost item (-1). Note: out-of-range index is valid. s[-4:5] == s[1:5] == [2,3,4,5] # index 5 is out-of-range s[4:-6:-1] == [5,4,3,2,1] # index -6 is out-of-range 2. The default index of i and j (When index is omitted) was decided by the sign of k. For positive k, the start index is 0 (the leftmost item) and the stop index is the one after the rightmost item. s[:3] == s[0:3] == [1,2,3] s[1:] == s[1:5] == [2,3,4,5] For negative k, the start index is -1 (the rightmost item) and the stop index is one ahead of the leftmost item s[:2:-1] == s[-1:2:-1] == [5,4] s[3::-1] == s[3:-6:-1] == [4,3,2,1] 3. The items pick-up order was decided by the sign of k. For positive k, the direction is toward the right. For negative k, it is toward the left. s[1:4] == [2,3,4] s[3:0:-1] == [4,3,2] 4. Invalid slice will return an empty [] s[2:0] == [] ----- --Jach From nospam at please.ty Fri Aug 6 04:09:42 2021 From: nospam at please.ty (jak) Date: Fri, 6 Aug 2021 10:09:42 +0200 Subject: Ask for help on using re References: <904b3a0e-9e0f-401a-8bb0-cf14de5a8a85n@googlegroups.com> Message-ID: Il 05/08/2021 11:40, Jach Feng ha scritto: > I want to distinguish between numbers with/without a dot attached: > >>>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' >>>> re.compile(r'ch \d{1,}[.]').findall(text) > ['ch 1.', 'ch 23.'] >>>> re.compile(r'ch \d{1,}[^.]').findall(text) > ['ch 23', 'ch 4 ', 'ch 56 '] > > I can guess why the 'ch 23' appears in the second list. But how to get rid of it? > > --Jach > import re t = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' r = re.compile(r'(ch +\d+\.)|(ch +\d+)', re.M) res = r.findall(t) dot = [x[1] for x in res if x[1] != ''] udot = [x[0] for x in res if x[0] != ''] print(f"dot: {dot}") print(f"undot: {udot}") out: dot: ['ch 4', 'ch 56'] undot: ['ch 1.', 'ch 23.'] From jfong at ms4.hinet.net Fri Aug 6 06:57:38 2021 From: jfong at ms4.hinet.net (Jach Feng) Date: Fri, 6 Aug 2021 03:57:38 -0700 (PDT) Subject: Ask for help on using re In-Reply-To: References: <904b3a0e-9e0f-401a-8bb0-cf14de5a8a85n@googlegroups.com> Message-ID: <296739fe-87a5-457d-b541-46c92620cc57n@googlegroups.com> jak ? 2021?8?6? ?????4:10:05 [UTC+8] ?????? > Il 05/08/2021 11:40, Jach Feng ha scritto: > > I want to distinguish between numbers with/without a dot attached: > > > >>>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' > >>>> re.compile(r'ch \d{1,}[.]').findall(text) > > ['ch 1.', 'ch 23.'] > >>>> re.compile(r'ch \d{1,}[^.]').findall(text) > > ['ch 23', 'ch 4 ', 'ch 56 '] > > > > I can guess why the 'ch 23' appears in the second list. But how to get rid of it? > > > > --Jach > > > import re > t = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' > r = re.compile(r'(ch +\d+\.)|(ch +\d+)', re.M) > > res = r.findall(t) > > dot = [x[1] for x in res if x[1] != ''] > udot = [x[0] for x in res if x[0] != ''] > > print(f"dot: {dot}") > print(f"undot: {udot}") > > out: > > dot: ['ch 4', 'ch 56'] > undot: ['ch 1.', 'ch 23.'] > r = re.compile(r'(ch +\d+\.)|(ch +\d+)', re.M) That's an interest solution! Where the '|' operator in re.compile() was documented? --Jach From nospam at please.ty Fri Aug 6 10:17:59 2021 From: nospam at please.ty (jak) Date: Fri, 6 Aug 2021 16:17:59 +0200 Subject: Ask for help on using re References: <904b3a0e-9e0f-401a-8bb0-cf14de5a8a85n@googlegroups.com> <296739fe-87a5-457d-b541-46c92620cc57n@googlegroups.com> Message-ID: Il 06/08/2021 12:57, Jach Feng ha scritto: > jak ? 2021?8?6? ?????4:10:05 [UTC+8] ?????? >> Il 05/08/2021 11:40, Jach Feng ha scritto: >>> I want to distinguish between numbers with/without a dot attached: >>> >>>>>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' >>>>>> re.compile(r'ch \d{1,}[.]').findall(text) >>> ['ch 1.', 'ch 23.'] >>>>>> re.compile(r'ch \d{1,}[^.]').findall(text) >>> ['ch 23', 'ch 4 ', 'ch 56 '] >>> >>> I can guess why the 'ch 23' appears in the second list. But how to get rid of it? >>> >>> --Jach >>> >> import re >> t = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' >> r = re.compile(r'(ch +\d+\.)|(ch +\d+)', re.M) >> >> res = r.findall(t) >> >> dot = [x[1] for x in res if x[1] != ''] >> udot = [x[0] for x in res if x[0] != ''] >> >> print(f"dot: {dot}") >> print(f"undot: {udot}") >> >> out: >> >> dot: ['ch 4', 'ch 56'] >> undot: ['ch 1.', 'ch 23.'] >> r = re.compile(r'(ch +\d+\.)|(ch +\d+)', re.M) > That's an interest solution! Where the '|' operator in re.compile() was documented? > > --Jach > I honestly can't tell you, I've been using it for over 30 years. In any case you can find some traces of it in the "regular expressions quick reference" on the site https://regex101.com (bottom right side). From nospam at please.ty Fri Aug 6 10:37:43 2021 From: nospam at please.ty (jak) Date: Fri, 6 Aug 2021 16:37:43 +0200 Subject: Ask for help on using re References: <904b3a0e-9e0f-401a-8bb0-cf14de5a8a85n@googlegroups.com> <296739fe-87a5-457d-b541-46c92620cc57n@googlegroups.com> Message-ID: Il 06/08/2021 16:17, jak ha scritto: > Il 06/08/2021 12:57, Jach Feng ha scritto: >> jak ? 2021?8?6? ?????4:10:05 [UTC+8] ?????? >>> Il 05/08/2021 11:40, Jach Feng ha scritto: >>>> I want to distinguish between numbers with/without a dot attached: >>>> >>>>>>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' >>>>>>> re.compile(r'ch \d{1,}[.]').findall(text) >>>> ['ch 1.', 'ch 23.'] >>>>>>> re.compile(r'ch \d{1,}[^.]').findall(text) >>>> ['ch 23', 'ch 4 ', 'ch 56 '] >>>> >>>> I can guess why the 'ch 23' appears in the second list. But how to >>>> get rid of it? >>>> >>>> --Jach >>>> >>> import re >>> t = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' >>> r = re.compile(r'(ch +\d+\.)|(ch +\d+)', re.M) >>> >>> res = r.findall(t) >>> >>> dot = [x[1] for x in res if x[1] != ''] >>> udot = [x[0] for x in res if x[0] != ''] >>> >>> print(f"dot: {dot}") >>> print(f"undot: {udot}") >>> >>> out: >>> >>> dot: ['ch 4', 'ch 56'] >>> undot: ['ch 1.', 'ch 23.'] >>> r = re.compile(r'(ch +\d+\.)|(ch +\d+)', re.M) >> That's an interest solution! Where the '|' operator in re.compile() >> was documented? >> >> --Jach >> > > I honestly can't tell you, I've been using it for over 30 years. In any > case you can find some traces of it in the "regular expressions quick > reference" on the site https://regex101.com (bottom right side). > ...if I'm not mistaken, the '|' it is part of normal regular expressions, so it is not a specific extension of the python libraries. Perhaps this is why you don't find any documentation on it. From jon+usenet at unequivocal.eu Fri Aug 6 10:44:19 2021 From: jon+usenet at unequivocal.eu (Jon Ribbens) Date: Fri, 6 Aug 2021 14:44:19 -0000 (UTC) Subject: Ask for help on using re References: <904b3a0e-9e0f-401a-8bb0-cf14de5a8a85n@googlegroups.com> <296739fe-87a5-457d-b541-46c92620cc57n@googlegroups.com> Message-ID: On 2021-08-06, jak wrote: > Il 06/08/2021 16:17, jak ha scritto: >> Il 06/08/2021 12:57, Jach Feng ha scritto: >>> That's an interest solution! Where the '|' operator in re.compile() >>> was documented? >> >> I honestly can't tell you, I've been using it for over 30 years. In any >> case you can find some traces of it in the "regular expressions quick >> reference" on the site https://regex101.com (bottom right side). > > ...if I'm not mistaken, the '|' it is part of normal regular > expressions, so it is not a specific extension of the python libraries. > Perhaps this is why you don't find any documentation on it. The Python documentation fully describes the regular expression syntax that the 're' module supports, including features that are widely supported by different regular expression systems and also Python extensions. '|' is documented here: https://docs.python.org/3/library/re.html#index-13 From bdorestand at example.com Fri Aug 6 13:31:26 2021 From: bdorestand at example.com (Boris Dorestand) Date: Fri, 06 Aug 2021 14:31:26 -0300 Subject: on slices, negative indices, which are the equivalent procedures? References: <86sfznhk1f.fsf@example.com> <86czqre92v.fsf@example.com> <00316df8-b5e3-4240-8e8d-6d1439a5356bn@googlegroups.com> Message-ID: <86y29ecwep.fsf@example.com> Jach Feng writes: >> >>>>> s = "Jack Brandom" >> >>>>> s[3 : -13 : -1] >> >> 'kcaJ' >> >> I have no idea how to replace that -13 with a positive index. Is it >> >> possible at all? > That's not possible because a positive index is relative to the leftmost item 0 And the middle index is always exclusive, so we can't go to the left of 0 and remain positive. Okay, I think that answers it. It's not possible at all. > Below is some rules of slice usage which I collected sometimes ago. > ----- > slice s[i:j:k] > The result is from start index i to stop index j (excluded) in step k (default is 1). i, j, k can be positive or negative. For example: s = [1, 2, 3, 4, 5] > 1. Positive index is relative to the leftmost item (0), negative index is relative to the rightmost item (-1). Note: out-of-range index is valid. > s[-4:5] == s[1:5] == [2,3,4,5] # index 5 is out-of-range > s[4:-6:-1] == [5,4,3,2,1] # index -6 is out-of-range > 2. The default index of i and j (When index is omitted) was decided by the sign of k. > For positive k, the start index is 0 (the leftmost item) and the stop index is the one after the rightmost item. > s[:3] == s[0:3] == [1,2,3] > s[1:] == s[1:5] == [2,3,4,5] > For negative k, the start index is -1 (the rightmost item) and the stop index is one ahead of the leftmost item > s[:2:-1] == s[-1:2:-1] == [5,4] > s[3::-1] == s[3:-6:-1] == [4,3,2,1] > 3. The items pick-up order was decided by the sign of k. For positive k, the direction is toward the right. For negative k, it is toward the left. > s[1:4] == [2,3,4] > s[3:0:-1] == [4,3,2] > 4. Invalid slice will return an empty [] > s[2:0] == [] Thank you. This helped a bit more. So now I propose the following simulation. Can anyone simplify this? Thanks! --8<---------------cut here---------------start------------->8--- def mySlice(it, beg, end, step = 1): """Simulates Python slices.""" if step is None: step = 1 assert step != 0, "step = 0 not allowed" ret = [] cur = beg if step > 0: return mySlicePositiveStep(it, beg, end, step) else: return mySliceNegativeStep(it, beg, end, step) def mySliceNegativeStep(it, beg, end, step = -1): """Assume STEP is always negative. The difference between positive and neative step is that it reverts the orientation of the loop, but the loop always begins at BEG, never at END. """ ret = [] if beg == None: beg = -1 if end == None: end = -len(it) - 1 if beg >= 0: # how to translate positive indices to negative ones beg = -len(it) + beg if end >= 0: end = -len(it) + end cur = beg # begin here while cur > end: # stop as soon as you arrive at END ret.append(it[cur]) cur += step return ret def mySlicePositiveStep(it, beg, end, step = 1): """Assume STEP is always positive. But if BEG or END are negative, we apply the equivalence rule BEG == LEN(IT) + BEG. For example, if BEG is -1 and LEN(IT) == 10, then BEG is equivalent to 9 == 10 + -1. (Similarly for END.) """ ret = [] if beg == None: beg = 0 if end == None: end = len(it) if beg < 0: beg = len(it) + beg if end < 0: end = len(it) + end cur = beg while cur < end: ret.append(it[cur]) cur += step return ret --8<---------------cut here---------------end--------------->8--- From rosuav at gmail.com Fri Aug 6 18:58:49 2021 From: rosuav at gmail.com (Chris Angelico) Date: Sat, 7 Aug 2021 08:58:49 +1000 Subject: on slices, negative indices, which are the equivalent procedures? In-Reply-To: <86y29ecwep.fsf@example.com> References: <86sfznhk1f.fsf@example.com> <86czqre92v.fsf@example.com> <00316df8-b5e3-4240-8e8d-6d1439a5356bn@googlegroups.com> <86y29ecwep.fsf@example.com> Message-ID: On Sat, Aug 7, 2021 at 5:22 AM Boris Dorestand wrote: > > Jach Feng writes: > > >> >>>>> s = "Jack Brandom" > >> >>>>> s[3 : -13 : -1] > >> >> 'kcaJ' > >> >> I have no idea how to replace that -13 with a positive index. Is it > >> >> possible at all? > > That's not possible because a positive index is relative to the leftmost item 0 > > And the middle index is always exclusive, so we can't go to the left of > 0 and remain positive. Okay, I think that answers it. It's not > possible at all. > An absent index isn't the same as any specific positive value, so, yeah, it's not possible to replace it with a positive index. It IS possible to replace it with None. >>> s = "Jack Brandom" >>> s[3:None:-1] 'kcaJ' You could implement equivalent logic in your function. ChrisA From nospam at please.ty Sat Aug 7 05:18:58 2021 From: nospam at please.ty (jak) Date: Sat, 7 Aug 2021 11:18:58 +0200 Subject: Ask for help on using re References: <904b3a0e-9e0f-401a-8bb0-cf14de5a8a85n@googlegroups.com> Message-ID: Il 07/08/2021 04:23, Jach Feng ha scritto: > jak ? 2021?8?6? ?????4:10:05 [UTC+8] ?????? >> Il 05/08/2021 11:40, Jach Feng ha scritto: >>> I want to distinguish between numbers with/without a dot attached: >>> >>>>>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' >>>>>> re.compile(r'ch \d{1,}[.]').findall(text) >>> ['ch 1.', 'ch 23.'] >>>>>> re.compile(r'ch \d{1,}[^.]').findall(text) >>> ['ch 23', 'ch 4 ', 'ch 56 '] >>> >>> I can guess why the 'ch 23' appears in the second list. But how to get rid of it? >>> >>> --Jach >>> >> import re >> t = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' >> r = re.compile(r'(ch +\d+\.)|(ch +\d+)', re.M) >> >> res = r.findall(t) >> >> dot = [x[1] for x in res if x[1] != ''] >> udot = [x[0] for x in res if x[0] != ''] >> >> print(f"dot: {dot}") >> print(f"undot: {udot}") >> >> out: >> >> dot: ['ch 4', 'ch 56'] >> undot: ['ch 1.', 'ch 23.'] > The result can be influenced by the order of re patterns? > >>>> import re >>>> t = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' >>>> re.compile(r'(ch +\d+\.)|(ch +\d+)', re.M).findall(t) > [('ch 1.', ''), ('ch 23.', ''), ('', 'ch 4'), ('', 'ch 56')] > >>>> re.compile(r'(ch +\d+)|(ch +\d+\.)', re.M).findall(t) > [('ch 1', ''), ('ch 23', ''), ('ch 4', ''), ('ch 56', '')] > > --Jach > Yes, when the patterns intersect each other as in your case. the difference between the 2 patterns is the "." in addition. The logical or does not continue checking when the condition is satisfied, so it is a good idea, in these cases, to search for the most complete patterns before the others. From nospam at please.ty Sat Aug 7 05:33:47 2021 From: nospam at please.ty (jak) Date: Sat, 7 Aug 2021 11:33:47 +0200 Subject: Ask for help on using re References: <904b3a0e-9e0f-401a-8bb0-cf14de5a8a85n@googlegroups.com> Message-ID: Il 07/08/2021 11:18, jak ha scritto: > Il 07/08/2021 04:23, Jach Feng ha scritto: >> jak ? 2021?8?6? ?????4:10:05 [UTC+8] ?????? >>> Il 05/08/2021 11:40, Jach Feng ha scritto: >>>> I want to distinguish between numbers with/without a dot attached: >>>> >>>>>>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' >>>>>>> re.compile(r'ch \d{1,}[.]').findall(text) >>>> ['ch 1.', 'ch 23.'] >>>>>>> re.compile(r'ch \d{1,}[^.]').findall(text) >>>> ['ch 23', 'ch 4 ', 'ch 56 '] >>>> >>>> I can guess why the 'ch 23' appears in the second list. But how to >>>> get rid of it? >>>> >>>> --Jach >>>> >>> import re >>> t = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' >>> r = re.compile(r'(ch +\d+\.)|(ch +\d+)', re.M) >>> >>> res = r.findall(t) >>> >>> dot = [x[1] for x in res if x[1] != ''] >>> udot = [x[0] for x in res if x[0] != ''] >>> >>> print(f"dot: {dot}") >>> print(f"undot: {udot}") >>> >>> out: >>> >>> dot: ['ch 4', 'ch 56'] >>> undot: ['ch 1.', 'ch 23.'] >> The result can be influenced by the order of re patterns? >> >>>>> import re >>>>> t = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' >>>>> re.compile(r'(ch +\d+\.)|(ch +\d+)', re.M).findall(t) >> [('ch 1.', ''), ('ch 23.', ''), ('', 'ch 4'), ('', 'ch 56')] >> >>>>> re.compile(r'(ch +\d+)|(ch +\d+\.)', re.M).findall(t) >> [('ch 1', ''), ('ch 23', ''), ('ch 4', ''), ('ch 56', '')] >> >> --Jach >> > Yes, when the patterns intersect each other as in your case. the > difference between the 2 patterns is the "." in addition. The logical or > does not continue checking when the condition is satisfied, so it is a > good idea, in these cases, to search for the most complete patterns > before the others. > > PS ... the behavior of the logical or that I have described is not typical of regular expressions but it is common in all programming languages. From greg.ewing at canterbury.ac.nz Sat Aug 7 11:17:43 2021 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Sun, 8 Aug 2021 03:17:43 +1200 Subject: on slices, negative indices, which are the equivalent procedures? In-Reply-To: <86czqre92v.fsf@example.com> References: <86sfznhk1f.fsf@example.com> <86czqre92v.fsf@example.com> Message-ID: On 6/08/21 12:00 pm, Jack Brandom wrote: > It seems > that I'd begin at position 3 (that's "k" which I save somewhere), then I > subtract 1 from 3, getting 2 (that's "c", which I save somewhere), then > I subtract 1 from 2, getting 1 (that's "a", ...), then I subtract 1 from > 1, getting 0 (that's J, ...), so I got "kcaJ" but my counter is 0 not > -13, which was my stopping point. You need to first replace any negative or missing indices with equivalent indices measured from the start of the string. When you do that in this example, you end up iterating backwards from 3 and stopping at -1. -- Greg From drmjws at yahoo.com Fri Aug 6 23:34:46 2021 From: drmjws at yahoo.com (MICHAEL J W SMITH) Date: Sat, 7 Aug 2021 03:34:46 +0000 (UTC) Subject: CODING PAGE ACCESS References: <1435003711.542499.1628307286677.ref@mail.yahoo.com> Message-ID: <1435003711.542499.1628307286677@mail.yahoo.com> I downloaded python. I selected it from the start menu. I clicked on:- Python 3-9New I got:- IDLE (Python 3.9 64-bit) Python 3.9 (64-bit) Python 3.9 Manuals (64-bit) Python 3.9 Module Docs (64-bit) I wish to access the page where I do coding.I would appreciate help, either directly, or with information as to where I can get help.Thank you so much! From jfong at ms4.hinet.net Fri Aug 6 22:23:55 2021 From: jfong at ms4.hinet.net (Jach Feng) Date: Fri, 6 Aug 2021 19:23:55 -0700 (PDT) Subject: Ask for help on using re In-Reply-To: References: <904b3a0e-9e0f-401a-8bb0-cf14de5a8a85n@googlegroups.com> Message-ID: jak ? 2021?8?6? ?????4:10:05 [UTC+8] ?????? > Il 05/08/2021 11:40, Jach Feng ha scritto: > > I want to distinguish between numbers with/without a dot attached: > > > >>>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' > >>>> re.compile(r'ch \d{1,}[.]').findall(text) > > ['ch 1.', 'ch 23.'] > >>>> re.compile(r'ch \d{1,}[^.]').findall(text) > > ['ch 23', 'ch 4 ', 'ch 56 '] > > > > I can guess why the 'ch 23' appears in the second list. But how to get rid of it? > > > > --Jach > > > import re > t = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' > r = re.compile(r'(ch +\d+\.)|(ch +\d+)', re.M) > > res = r.findall(t) > > dot = [x[1] for x in res if x[1] != ''] > udot = [x[0] for x in res if x[0] != ''] > > print(f"dot: {dot}") > print(f"undot: {udot}") > > out: > > dot: ['ch 4', 'ch 56'] > undot: ['ch 1.', 'ch 23.'] The result can be influenced by the order of re patterns? >>> import re >>> t = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' >>> re.compile(r'(ch +\d+\.)|(ch +\d+)', re.M).findall(t) [('ch 1.', ''), ('ch 23.', ''), ('', 'ch 4'), ('', 'ch 56')] >>> re.compile(r'(ch +\d+)|(ch +\d+\.)', re.M).findall(t) [('ch 1', ''), ('ch 23', ''), ('ch 4', ''), ('ch 56', '')] --Jach From python at mrabarnett.plus.com Sat Aug 7 15:31:08 2021 From: python at mrabarnett.plus.com (MRAB) Date: Sat, 7 Aug 2021 20:31:08 +0100 Subject: CODING PAGE ACCESS In-Reply-To: <1435003711.542499.1628307286677@mail.yahoo.com> References: <1435003711.542499.1628307286677.ref@mail.yahoo.com> <1435003711.542499.1628307286677@mail.yahoo.com> Message-ID: <193446a2-1304-eca7-e807-4347c39588f4@mrabarnett.plus.com> On 2021-08-07 04:34, MICHAEL J W SMITH via Python-list wrote: > I downloaded python. I selected it from the start menu. I clicked on:- > Python 3-9New > I got:- > IDLE (Python 3.9 64-bit) > Python 3.9 (64-bit) > Python 3.9 Manuals (64-bit) > Python 3.9 Module Docs (64-bit) > I wish to access the page where I do coding.I would appreciate help, either directly, or with information as to where I can get help.Thank you so much! > The Manual contains a tutorial. You can use IDLE to use Python interactively or edit programs. From tjreedy at udel.edu Sat Aug 7 15:24:50 2021 From: tjreedy at udel.edu (Terry Reedy) Date: Sat, 7 Aug 2021 15:24:50 -0400 Subject: CODING PAGE ACCESS In-Reply-To: <1435003711.542499.1628307286677@mail.yahoo.com> References: <1435003711.542499.1628307286677.ref@mail.yahoo.com> <1435003711.542499.1628307286677@mail.yahoo.com> Message-ID: On 8/6/2021 11:34 PM, MICHAEL J W SMITH via Python-list wrote: > I downloaded python. I selected it from the start menu. I clicked on:- > Python 3-9New 'New' goes away after the first access > I got:- > IDLE (Python 3.9 64-bit) This is the included editor and enhanced interactive shell for writing and testing Python code. Doc is available on the Help menu and at https://docs.python.org/3/library/idle.html > Python 3.9 (64-bit) This is the standard interactive shell. > Python 3.9 Manuals (64-bit) The online manuals > Python 3.9 Module Docs (64-bit) The 'help' version of module docs generated from the installed modules. > I wish to access the page where I do coding.I would appreciate help, either directly, or with information as to where I can get help.Thank you so much! > -- Terry Jan Reedy From brgl at bgdev.pl Sun Aug 8 15:24:21 2021 From: brgl at bgdev.pl (Bartosz Golaszewski) Date: Sun, 8 Aug 2021 21:24:21 +0200 Subject: Defining a Python enum in a C extension - am I doing this right? In-Reply-To: References: Message-ID: On Fri, Aug 6, 2021 at 9:02 PM Serhiy Storchaka wrote: > > 03.08.21 13:03, Bartosz Golaszewski ????: > > Just a follow-up: this is how I did it eventually: > > I think it can be simpler. > > 1. No need to create the __main__ module. You can just create a dict. If > some attributes are required (e.g. __name__) it is easy to set them in > the Python code (__name__ = 'pycenum'). > > 2. No need to import the enum module in the C code. It is easier to do > it in the Python code. > Don't you need the '__import__' attribute for that? It's linked to point #1. > 3. Can you define your DummyType in the Python code instead of the C > code? Even if you need to create in the C code, it may be better to > define your enum class inside a dummy DummyType. It will set correct > __qualname__ of the enum class: > This code is a PoC for the real code I want to use it in where the type embedding the enum is defined in C. > __name__ = 'pycenum' > import enum > class DummyType: > class FooBar(enum.Enum): > ... > > 4. Did you consider idea of making DummyType a heap-allocated type? It > may be easy to create new type with PyType_FromModuleAndSpec(), and it > is more stable API, and the type is not immutable, so it is easy to add > new attributes with PyObject_SetAttrString(). > Makes sense, thanks, I'll try it. Bart From sjeik_appie at hotmail.com Mon Aug 9 09:21:13 2021 From: sjeik_appie at hotmail.com (Albert-Jan Roskam) Date: Mon, 09 Aug 2021 15:21:13 +0200 Subject: Tracing in a Flask application In-Reply-To: Message-ID: Hi, logging.basicConfig(level="DEBUG") ..in e.g __init__.py AJ On 4 Aug 2021 23:26, Javi D R wrote: Hi I would like to do some tracing in a flask. I have been able to trace request in plain python requests using sys.settrace(), but this doesnt work with Flask. Moreover, what i want to trace is in a flask application, when an endpoint is called, what was the request, which parts of the code was executed (i think i can still do it with settrace) and what is the response sent by the application Can you help me to understand which services i can use to do this? Thanks -- https://mail.python.org/mailman/listinfo/python-list From roland.em0001 at googlemail.com Mon Aug 9 13:01:52 2021 From: roland.em0001 at googlemail.com (Roland Mueller) Date: Mon, 9 Aug 2021 20:01:52 +0300 Subject: =?UTF-8?Q?Re=3A_Flask_=E2=80=93_how_to_write_csv_file_=26_save_using_pre?= =?UTF-8?Q?filled_value_of_the_filename_=28response=2Eheaders=5B=22Content=2DDisp?= =?UTF-8?Q?osition=22=5D=3D=22attachment=3B_filename=3Dxxx=22=29?= In-Reply-To: References: Message-ID: pe 6. elok. 2021 klo 19.15 MRAB (python at mrabarnett.plus.com) kirjoitti: > On 2021-08-06 16:50, Suretha Weweje wrote: > > I am trying to upload a CSV file with flask, read and process one line > at a > > time while iterating through all rows of the file and write the results > > back to a new CSV file. My python script produces the correct results on > > its own, but I am not able to get the same results when using Flask. I am > > new to flask. > > > [snip] > > > > csv_reader = csv.reader(new) > > > [snip] > > > > *mywriter = csv.DictWriter('results.csv', fieldnames=headers_new)* > [snip] > > The problem has nothing to do with Flask. > > 'csv.reader' and 'csv.DictWriter' expect a file object, but you're > passing them strings. > -- > https://mail.python.org/mailman/listinfo/python-list May be you should use io.StringIO to create a file/stream from an input string. from io import StringIO s = "\n".join(["a","b","c"]) + "\n" for line in StringIO(s): print(f"\t{line}") BR, Roland From johndavidgriner74 at gmail.com Sun Aug 8 17:04:01 2021 From: johndavidgriner74 at gmail.com (John Griner) Date: Sun, 8 Aug 2021 17:04:01 -0400 Subject: John Griner Python Tutor Available Message-ID: <73BF4747-671F-4364-AC51-3C5C05BE1C4C@hxcore.ol> To whom it may concern, I am not sure if this is appropriate, but I would like to somehow `advertise' my classes. I have a free workshop: Intro to Python: Data Wrangling, Visualization, List and Tuples and a series that consist of 3 parts, (1) Data Wrangling (2) Data Visualization and (3) List and Tuples. The free workshop is a broad overview of the series that consist of 3 classes. It was designed for the beginner, but someone with intermediate to advanced knowledge of Python may also benefit. I also have 2 other more advanced courses, and after sometime, I will offer other, more advanced courses. If you would like the link to join, I can provide the link, and if you ae unsure of whether or not you want to take the courses, just take the free workshop. Best, John Griner [1][IMG] Virus-free. [2]www.avast.com References Visible links 1. https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=emailclient&utm_term=icon 2. https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=emailclient&utm_term=link From himanshug092003 at gmail.com Sun Aug 8 23:12:52 2021 From: himanshug092003 at gmail.com (Himanshu Gupta) Date: Mon, 9 Aug 2021 08:42:52 +0530 Subject: Errors and some bugs Message-ID: While running some pip command to install spacy package for ver3.9 I always face trouble can you provide a solution From lukas at some.engineering Mon Aug 9 08:25:27 2021 From: lukas at some.engineering (=?UTF-8?Q?Lukas_L=C3=B6sche?=) Date: Mon, 9 Aug 2021 14:25:27 +0200 Subject: annotations cause dataclass fields type side effects Message-ID: I'm on Python 3.9.6 and trying to make sense of the following behaviour: >>> from dataclasses import dataclass, fields >>> @dataclass ... class Foobar: ... name: str ... >>> fields(Foobar)[0].type >>> type(fields(Foobar)[0].type) >>> from __future__ import annotations >>> from dataclasses import dataclass, fields >>> >>> @dataclass ... class Foobar: ... name: str ... >>> fields(Foobar)[0].type 'str' >>> type(fields(Foobar)[0].type) I have a validation function that checks if the types of all fields in a dataclass are what they are supposed to be. But as soon as I import annotations from __future__ this validation breaks as the arg that I'm passing to isinstance() is no longer a type class but a string. What am I doing wrong? Thanks, -- Lukas From PythonList at DancesWithMice.info Mon Aug 9 15:11:24 2021 From: PythonList at DancesWithMice.info (dn) Date: Tue, 10 Aug 2021 07:11:24 +1200 Subject: Errors and some bugs In-Reply-To: References: Message-ID: <39372d59-ec00-ff3f-7946-169caec0db37@DancesWithMice.info> On 09/08/2021 15.12, Himanshu Gupta wrote: > While running some pip command to install spacy package for ver3.9 I always > face trouble can you provide a solution The short answer is "yes", but what is the problem? Please copy-paste the install command and the (full) error message, from the terminal-session into an email response, and we'll try to help... -- Regards, =dn From tdldev at gmail.com Mon Aug 9 16:00:41 2021 From: tdldev at gmail.com (Jack Dangler) Date: Mon, 9 Aug 2021 16:00:41 -0400 Subject: CODING PAGE ACCESS In-Reply-To: <193446a2-1304-eca7-e807-4347c39588f4@mrabarnett.plus.com> References: <1435003711.542499.1628307286677.ref@mail.yahoo.com> <1435003711.542499.1628307286677@mail.yahoo.com> <193446a2-1304-eca7-e807-4347c39588f4@mrabarnett.plus.com> Message-ID: Or open a terminal and type 'python3' ... Or open an editor, type in a py program, save it as "myfirstcode.py" and then at the console type 'python3 ./myfirstcode.py' and hit return... There are a number of choices to get there - that's the tenet of Linux. It's all about choice. On 8/7/21 3:31 PM, MRAB wrote: > On 2021-08-07 04:34, MICHAEL J W SMITH via Python-list wrote: >> I downloaded python. I selected it from the start menu. I clicked on:- >> Python 3-9New >> I got:- >> IDLE (Python 3.9 64-bit) >> Python 3.9 (64-bit) >> Python 3.9 Manuals (64-bit) >> Python 3.9 Module Docs (64-bit) >> I wish to access the page where I do coding.I would appreciate help, >> either directly, or with information as to where I can get help.Thank >> you so much! >> > The Manual contains a tutorial. > > You can use IDLE to use Python interactively or edit programs. From jbrandom at example.com Mon Aug 9 14:41:11 2021 From: jbrandom at example.com (Jack Brandom) Date: Mon, 09 Aug 2021 15:41:11 -0300 Subject: on slices, negative indices, which are the equivalent procedures? References: <86sfznhk1f.fsf@example.com> <86czqre92v.fsf@example.com> Message-ID: <86o8a6cvg8.fsf@jevedi.xotimo> Greg Ewing writes: > On 6/08/21 12:00 pm, Jack Brandom wrote: >> It seems >> that I'd begin at position 3 (that's "k" which I save somewhere), then I >> subtract 1 from 3, getting 2 (that's "c", which I save somewhere), then >> I subtract 1 from 2, getting 1 (that's "a", ...), then I subtract 1 from >> 1, getting 0 (that's J, ...), so I got "kcaJ" but my counter is 0 not >> -13, which was my stopping point. > > You need to first replace any negative or missing indices with > equivalent indices measured from the start of the string. > > When you do that in this example, you end up iterating backwards from 3 > and stopping at -1. Yeah, that makes sense now. But it sucks that the rule for replacing negative indices is sometimes missing index and sometimes positive index. (That is, we can't always use positive indices. Sometimes we must use no index at all. I mean that's how it looks to my eyes.) From hrouselle at jevedi.xotimo Mon Aug 9 17:07:42 2021 From: hrouselle at jevedi.xotimo (Hope Rouselle) Date: Mon, 09 Aug 2021 18:07:42 -0300 Subject: some problems for an introductory python test Message-ID: <868s1acoo1.fsf@jevedi.xotimo> I'm looking for questions to put on a test for students who never had any experience with programming, but have learned to use Python's procedures, default arguments, if-else, strings, tuples, lists and dictionaries. (There's no OOP at all in this course. Students don't even write ls.append(...). They write list.append(ls, ...)). I'd like to put questions that they would have to write procedures that would would be real-world type of stuff, without error checking, exceptions and such. So if you think of something more or less cool that uses loops, we can sometimes simplify it by assuming the input has a certain fixed size. I came up with the following question. Using strings of length 5 (always), write a procedure histogram(s) that consumes a string and produces a dictionary whose keys are each substrings (of the string) of length 1 and their corresponding values are the number of times each such substrings appear. For example, histogram("aaaaa") = {"a": 5}. Students can "loop through" the string by writing out s[0], s[1], s[2], s[3], s[4]. I'd like even better questions. I'd like questions that would tell them to write procedures that would also have inverses, so that one could check the other of the other. (A second question would ask for the inverse, but hopefully real world stuff. One such question could be parsing a line separate by fields such as "root:0:0:mypass:Super User" and another that gives them ["root", 0, 0, ...] and asks them to write "root:0:0:mypass:..." You get the idea.) Students know how to use str(). But they don't know how to use type(), so they can't really check for the type of the input. I probably couldn't ask them to write a prototype of a tiny subset of pickle, say. I think you get the idea. I hope you can provide me with creativity. I have been looking at books, but every one I look at they introduce loops very quickly and off they go. Thank you! From rosuav at gmail.com Mon Aug 9 17:57:40 2021 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 10 Aug 2021 07:57:40 +1000 Subject: on slices, negative indices, which are the equivalent procedures? In-Reply-To: <86o8a6cvg8.fsf@jevedi.xotimo> References: <86sfznhk1f.fsf@example.com> <86czqre92v.fsf@example.com> <86o8a6cvg8.fsf@jevedi.xotimo> Message-ID: On Tue, Aug 10, 2021 at 7:24 AM Jack Brandom wrote: > > Greg Ewing writes: > > > On 6/08/21 12:00 pm, Jack Brandom wrote: > >> It seems > >> that I'd begin at position 3 (that's "k" which I save somewhere), then I > >> subtract 1 from 3, getting 2 (that's "c", which I save somewhere), then > >> I subtract 1 from 2, getting 1 (that's "a", ...), then I subtract 1 from > >> 1, getting 0 (that's J, ...), so I got "kcaJ" but my counter is 0 not > >> -13, which was my stopping point. > > > > You need to first replace any negative or missing indices with > > equivalent indices measured from the start of the string. > > > > When you do that in this example, you end up iterating backwards from 3 > > and stopping at -1. > > Yeah, that makes sense now. But it sucks that the rule for replacing > negative indices is sometimes missing index and sometimes positive > index. (That is, we can't always use positive indices. Sometimes we > must use no index at all. I mean that's how it looks to my eyes.) Sometimes, the index you need to use is the value None. You cannot use a positive number to indicate the position to the left of zero - at least, not if you consider numbers to be on a number line. ChrisA From rosuav at gmail.com Mon Aug 9 18:00:02 2021 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 10 Aug 2021 08:00:02 +1000 Subject: some problems for an introductory python test In-Reply-To: <868s1acoo1.fsf@jevedi.xotimo> References: <868s1acoo1.fsf@jevedi.xotimo> Message-ID: On Tue, Aug 10, 2021 at 7:25 AM Hope Rouselle wrote: > I came up with the following question. Using strings of length 5 > (always), write a procedure histogram(s) that consumes a string and > produces a dictionary whose keys are each substrings (of the string) of > length 1 and their corresponding values are the number of times each > such substrings appear. For example, histogram("aaaaa") = {"a": 5}. > Students can "loop through" the string by writing out s[0], s[1], s[2], > s[3], s[4]. In other words, recreate collections.Counter? Seems decent, but you'll need to decide whether you want them to use defaultdict, use __missing__, or do it all manually. > I think you get the idea. I hope you can provide me with creativity. I > have been looking at books, but every one I look at they introduce loops > very quickly and off they go. Thank you! Probably because loops are kinda important? :) ChrisA From mats at wichmann.us Mon Aug 9 18:14:14 2021 From: mats at wichmann.us (Mats Wichmann) Date: Mon, 9 Aug 2021 16:14:14 -0600 Subject: some problems for an introductory python test In-Reply-To: <868s1acoo1.fsf@jevedi.xotimo> References: <868s1acoo1.fsf@jevedi.xotimo> Message-ID: <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> On 8/9/21 3:07 PM, Hope Rouselle wrote: > I'm looking for questions to put on a test for students who never had > any experience with programming, but have learned to use Python's > procedures, default arguments, if-else, strings, tuples, lists and > dictionaries. (There's no OOP at all in this course. Students don't > even write ls.append(...). They write list.append(ls, ...)). Nitpickery... there *is* OOP in the course, they just don't know it. Long long ago (over 20 yrs now) I developed a Python course for a commercial training provider, and in it I claimed one of the great things about Python was it supported all kinds of object oriented programming techniques, but you could also use it without doing anything object oriented. If I wrote a course now, I'd never make that claim, because everything you do in Python is pretty much object oriented. >>> x = list() >>> type(x) >>> dir(x) ['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', ' __lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'] list is a class and it has methods... it's "object-oriented"! Even if you do x = 2 + 3 you're actually creating an integer object with a value of 2, and calling its add method to add the integer object with the value of 3 to it. The syntax hides it, but in a way it's just convenience that it does so... >>> 2 + 3 5 >>> x = 2 >>> x.__add__(3) 5 sorry for nitpicking :) But... don't be afraid of letting them know it's OOP, and it''s not huge and complex and scary! From rosuav at gmail.com Mon Aug 9 20:34:54 2021 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 10 Aug 2021 10:34:54 +1000 Subject: some problems for an introductory python test In-Reply-To: <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> Message-ID: On Tue, Aug 10, 2021 at 8:19 AM Mats Wichmann wrote: > Even if you do > > x = 2 + 3 > > you're actually creating an integer object with a value of 2, and > calling its add method to add the integer object with the value of 3 to > it. The syntax hides it, but in a way it's just convenience that it does > so... > > >>> 2 + 3 > 5 > >>> x = 2 > >>> x.__add__(3) > 5 > > > sorry for nitpicking :) But... don't be afraid of letting them know > it's OOP, and it''s not huge and complex and scary! > Since we're nitpicking already, "2 + 3" isn't the same as "(2).__add__(3)"; among other things, it's able to call (3).__radd__(2) instead. Plus there's technicalities about type slots and such. If you want to highlight the OOP nature of Python, rather than looking at magic methods, I'd first look at polymorphism. You can add a pair of integers; you can add a pair of tuples; you can add a pair of strings. Each one logically adds two things together and gives a result, and they're all spelled the exact same way. Dunder methods are a way for custom classes to slot into that same polymorphism, but the polymorphism exists first and the dunders come later. ChrisA From mats at wichmann.us Mon Aug 9 23:39:37 2021 From: mats at wichmann.us (Mats Wichmann) Date: Mon, 9 Aug 2021 21:39:37 -0600 Subject: some problems for an introductory python test In-Reply-To: References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> Message-ID: On 8/9/21 6:34 PM, Chris Angelico wrote: > If you want to highlight the OOP nature of Python, rather than looking > at magic methods, I'd first look at polymorphism. You can add a pair > of integers; you can add a pair of tuples; you can add a pair of > strings. Each one logically adds two things together and gives a > result, and they're all spelled the exact same way. Dunder methods are > a way for custom classes to slot into that same polymorphism, but the > polymorphism exists first and the dunders come later. > > ChrisA > not disagreeing... and yeah I could have thought deeper about the answer, but I still think "notthing has been OOP" -> "yes it has, they just didn't realize it" was worth mentioning From rosuav at gmail.com Tue Aug 10 00:18:13 2021 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 10 Aug 2021 14:18:13 +1000 Subject: some problems for an introductory python test In-Reply-To: References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> Message-ID: On Tue, Aug 10, 2021 at 1:41 PM Mats Wichmann wrote: > > > On 8/9/21 6:34 PM, Chris Angelico wrote: > > > If you want to highlight the OOP nature of Python, rather than looking > > at magic methods, I'd first look at polymorphism. You can add a pair > > of integers; you can add a pair of tuples; you can add a pair of > > strings. Each one logically adds two things together and gives a > > result, and they're all spelled the exact same way. Dunder methods are > > a way for custom classes to slot into that same polymorphism, but the > > polymorphism exists first and the dunders come later. > > > > ChrisA > > > > not disagreeing... and yeah I could have thought deeper about the > answer, but I still think "notthing has been OOP" -> "yes it has, they > just didn't realize it" was worth mentioning Oh yes, absolutely agree. ChrisA From hrouselle at jevedi.xotimo Tue Aug 10 08:35:18 2021 From: hrouselle at jevedi.xotimo (Hope Rouselle) Date: Tue, 10 Aug 2021 09:35:18 -0300 Subject: on slices, negative indices, which are the equivalent procedures? References: <86sfznhk1f.fsf@example.com> <86czqre92v.fsf@example.com> <86o8a6cvg8.fsf@jevedi.xotimo> Message-ID: <86sfzhbhq1.fsf@jevedi.xotimo> Chris Angelico writes: > On Tue, Aug 10, 2021 at 7:24 AM Jack Brandom wrote: >> >> Greg Ewing writes: >> >> > On 6/08/21 12:00 pm, Jack Brandom wrote: >> >> It seems >> >> that I'd begin at position 3 (that's "k" which I save somewhere), then I >> >> subtract 1 from 3, getting 2 (that's "c", which I save somewhere), then >> >> I subtract 1 from 2, getting 1 (that's "a", ...), then I subtract 1 from >> >> 1, getting 0 (that's J, ...), so I got "kcaJ" but my counter is 0 not >> >> -13, which was my stopping point. >> > >> > You need to first replace any negative or missing indices with >> > equivalent indices measured from the start of the string. >> > >> > When you do that in this example, you end up iterating backwards from 3 >> > and stopping at -1. >> >> Yeah, that makes sense now. But it sucks that the rule for replacing >> negative indices is sometimes missing index and sometimes positive >> index. (That is, we can't always use positive indices. Sometimes we >> must use no index at all. I mean that's how it looks to my eyes.) > > Sometimes, the index you need to use is the value None. You cannot > use a positive number to indicate the position to the left of zero - > at least, not if you consider numbers to be on a number line. True --- I understand that now. (I think someone else in this thread had pointed that out too. But thanks for clarifying it.) From hrouselle at jevedi.xotimo Tue Aug 10 08:46:43 2021 From: hrouselle at jevedi.xotimo (Hope Rouselle) Date: Tue, 10 Aug 2021 09:46:43 -0300 Subject: some problems for an introductory python test References: <868s1acoo1.fsf@jevedi.xotimo> Message-ID: <868s19bh70.fsf@jevedi.xotimo> Chris Angelico writes: > On Tue, Aug 10, 2021 at 7:25 AM Hope Rouselle wrote: >> I came up with the following question. Using strings of length 5 >> (always), write a procedure histogram(s) that consumes a string and >> produces a dictionary whose keys are each substrings (of the string) of >> length 1 and their corresponding values are the number of times each >> such substrings appear. For example, histogram("aaaaa") = {"a": 5}. >> Students can "loop through" the string by writing out s[0], s[1], s[2], >> s[3], s[4]. > > In other words, recreate collections.Counter? Seems decent, but you'll > need to decide whether you want them to use defaultdict, use > __missing__, or do it all manually. Yes, the course introduces very little so there is a lot of recreation going on. Hm, I don't know defaultdict and I don't know how to use __missing__. The course does introduce dict.get(), though. If students use dict.get(), then the procedure could essentially be: def histogram(s): d = {} d[s[0]] = d.get(s[0], 0) + 1 d[s[1]] = d.get(s[1], 0) + 1 d[s[2]] = d.get(s[2], 0) + 1 d[s[3]] = d.get(s[3], 0) + 1 d[s[4]] = d.get(s[4], 0) + 1 return d >> I think you get the idea. I hope you can provide me with creativity. I >> have been looking at books, but every one I look at they introduce loops >> very quickly and off they go. Thank you! > > Probably because loops are kinda important? :) Totally important. But each course author thinks they know better. Sometimes a college professor can do very little to help her students. I am actually fond of functional programming as a first course using a language with as little syntax as possible. Python is very nice but it's not a small language. It's easy to see courses spending an entire semester on introducing syntax and this one is no different. I think it's more interesting to see all the syntax in a few minutes and spend the semester on strategies. From hrouselle at jevedi.xotimo Tue Aug 10 09:15:39 2021 From: hrouselle at jevedi.xotimo (Hope Rouselle) Date: Tue, 10 Aug 2021 10:15:39 -0300 Subject: some problems for an introductory python test References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> Message-ID: <86sfzha1ac.fsf@jevedi.xotimo> Mats Wichmann writes: > On 8/9/21 3:07 PM, Hope Rouselle wrote: >> I'm looking for questions to put on a test for students who never had >> any experience with programming, but have learned to use Python's >> procedures, default arguments, if-else, strings, tuples, lists and >> dictionaries. (There's no OOP at all in this course. Students don't >> even write ls.append(...). They write list.append(ls, ...)). > > Nitpickery... there *is* OOP in the course, they just don't know it. > > Long long ago (over 20 yrs now) I developed a Python course for a > commercial training provider, and in it I claimed one of the great > things about Python was it supported all kinds of object oriented > programming techniques, but you could also use it without doing > anything object oriented. If I wrote a course now, I'd never make that > claim, because everything you do in Python is pretty much object > oriented. > >>>> x = list() >>>> type(x) > >>>> dir(x) > ['__add__', '__class__', '__class_getitem__', '__contains__', > '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', > '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', > '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', > '__iter__', '__le__', '__len__', ' > __lt__', '__mul__', '__ne__', '__new__', '__reduce__', > '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', > '__setattr__', '__setitem__', '__sizeof__', '__str__', > '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', > 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'] > > list is a class and it has methods... it's "object-oriented"! > > > Even if you do > > x = 2 + 3 > > you're actually creating an integer object with a value of 2, and > calling its add method to add the integer object with the value of 3 > to it. The syntax hides it, but in a way it's just convenience that it > does so... > >>>> 2 + 3 > 5 >>>> x = 2 >>>> x.__add__(3) > 5 > > > sorry for nitpicking :) But... don't be afraid of letting them know > it's OOP, and it''s not huge and complex and scary! I totally agree with you but I didn't know that even numbers were like that in Python. In fact, I still don't quite believe it... >>> 2.__add__(3) SyntaxError: invalid syntax But then I tried: >>> (2).__add__(3) 5 Now I do believe it! :-) Awesome. I had no idea. (*) More opinions So, yeah, the idea of a course like that is to try to simplify the world to students, but it totally backfires in my opinion. There is so much syntax to learn, so many little details... We spend the entire semester discussing these little details. I posted here recently a study of the semantics of slices. When I finally got it, I concluded it's not very simple. The course introduces a few examples and expects students to get it all from these examples. I would rather not introduce slices but teach students enough to write procedures that give them the slices. The slices are the fish; learning to write the procedures is the know-how. (I'm fine with even teaching them how to write procedures to add or subtract numbers [and the rest of arithmetic], although none of them would find mysterious what is the meaning of arithmetic expressions such as 3 + 6 - 9, even taking precedence of operators into account. That's syntax they already know. If we teach them the syntax of procedures, we could be essentially done with syntax.) From hrouselle at jevedi.xotimo Tue Aug 10 09:48:01 2021 From: hrouselle at jevedi.xotimo (Hope Rouselle) Date: Tue, 10 Aug 2021 10:48:01 -0300 Subject: some problems for an introductory python test References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> Message-ID: <86lf599zse.fsf@jevedi.xotimo> Chris Angelico writes: [...] >> not disagreeing... and yeah I could have thought deeper about the >> answer, but I still think "notthing has been OOP" -> "yes it has, they >> just didn't realize it" was worth mentioning > > Oh yes, absolutely agree. At the same time, inside the machine nothing is OOP --- so all the OOP is no OOP at all and they just didn't realize it? This seems to show that OOP is about perspective. An essential thing for OOP is the keeping of states. Closures can keep state, so having procedures as first-class values allows us to say we are doing OOP too. (Arguments of procedures are messages and function application is message passing, with closures keeping a state --- and all the rest of OOP can be implemented with enough such functional technology.) In summary, OOP should not be defined as some special syntax, otherwise there is no OOP in ``2 + 2''. Having said that, I totally agree with all the nitpicking. From rosuav at gmail.com Tue Aug 10 14:47:42 2021 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 11 Aug 2021 04:47:42 +1000 Subject: some problems for an introductory python test In-Reply-To: <868s19bh70.fsf@jevedi.xotimo> References: <868s1acoo1.fsf@jevedi.xotimo> <868s19bh70.fsf@jevedi.xotimo> Message-ID: On Wed, Aug 11, 2021 at 4:14 AM Hope Rouselle wrote: > > Chris Angelico writes: > > > On Tue, Aug 10, 2021 at 7:25 AM Hope Rouselle wrote: > >> I came up with the following question. Using strings of length 5 > >> (always), write a procedure histogram(s) that consumes a string and > >> produces a dictionary whose keys are each substrings (of the string) of > >> length 1 and their corresponding values are the number of times each > >> such substrings appear. For example, histogram("aaaaa") = {"a": 5}. > >> Students can "loop through" the string by writing out s[0], s[1], s[2], > >> s[3], s[4]. > > > > In other words, recreate collections.Counter? Seems decent, but you'll > > need to decide whether you want them to use defaultdict, use > > __missing__, or do it all manually. > > Yes, the course introduces very little so there is a lot of recreation > going on. Hm, I don't know defaultdict and I don't know how to use > __missing__. The course does introduce dict.get(), though. If students > use dict.get(), then the procedure could essentially be: > > def histogram(s): > d = {} > d[s[0]] = d.get(s[0], 0) + 1 > d[s[1]] = d.get(s[1], 0) + 1 > d[s[2]] = d.get(s[2], 0) + 1 > d[s[3]] = d.get(s[3], 0) + 1 > d[s[4]] = d.get(s[4], 0) + 1 > return d There's nothing wrong with getting students to recreate things, but there are so many different levels on which you could do this, which will leave your more advanced students wondering what's legal. :) Here are several ways to do the same thing: >>> s = "hello world" >>> from collections import Counter; Counter(s) Counter({'l': 3, 'o': 2, 'h': 1, 'e': 1, ' ': 1, 'w': 1, 'r': 1, 'd': 1}) >>> from collections import defaultdict >>> hist = defaultdict(int) >>> for ltr in s: hist[ltr] += 1 ... >>> hist defaultdict(, {'h': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 1, 'w': 1, 'r': 1, 'd': 1}) >>> class Incrementer(dict): ... def __missing__(self, key): return 0 ... >>> hist = Incrementer() >>> for ltr in s: hist[ltr] += 1 ... >>> hist {'h': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 1, 'w': 1, 'r': 1, 'd': 1} >>> hist = {} >>> for ltr in s: hist[ltr] = hist.get(ltr, 0) + 1 ... >>> hist {'h': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 1, 'w': 1, 'r': 1, 'd': 1} >>> hist = {} >>> for ltr in s: ... if ltr in hist: hist[ltr] += 1 ... else: hist[ltr] = 1 ... >>> hist {'h': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 1, 'w': 1, 'r': 1, 'd': 1} >>> hist = {} >>> for ltr in s: ... try: hist[ltr] += 1 ... except KeyError: hist[ltr] = 1 ... >>> hist {'h': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 1, 'w': 1, 'r': 1, 'd': 1} A Counter shows the values ranked, all the others retain insertion order, but they all get to the same result. It seems *very* strange to have an exercise like this without looping. That seems counterproductive. But if you're expecting them to not use loops, you'll want to also be very clear about what other features they're allowed to use - or alternatively, stipulate what they ARE allowed to use, eg "Use only indexing and the get() method". ChrisA From rosuav at gmail.com Tue Aug 10 15:02:52 2021 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 11 Aug 2021 05:02:52 +1000 Subject: some problems for an introductory python test In-Reply-To: <86sfzha1ac.fsf@jevedi.xotimo> References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86sfzha1ac.fsf@jevedi.xotimo> Message-ID: On Wed, Aug 11, 2021 at 4:18 AM Hope Rouselle wrote: > > I totally agree with you but I didn't know that even numbers were like > that in Python. In fact, I still don't quite believe it... > > >>> 2.__add__(3) > SyntaxError: invalid syntax Yeah, that's because "2." looks like the beginning of a float. > But then I tried: > > >>> (2).__add__(3) > 5 > > Now I do believe it! :-) Awesome. I had no idea. You can also do it this way: >>> x = 2 >>> x.__add__(3) 5 But don't teach this; it ignores several problems. Notably, a subclass should be able to (re)define operators: >>> class FancyNumber(int): ... def __repr__(self): return "FancyNumber(%d)" % self ... def __add__(self, other): return type(self)(int(self) + other) ... def __radd__(self, other): return type(self)(other + int(self)) ... >>> FancyNumber(2) + 3 FancyNumber(5) >>> 2 + FancyNumber(3) FancyNumber(5) >>> FancyNumber(2).__add__(3) FancyNumber(5) >>> (2).__add__(FancyNumber(3)) 5 With the + operator, you always get a FancyNumber back. Explicitly calling the dunder method fails. (General principle: Dunder methods are for defining, not for calling, unless you're in the process of defining a dunder.) > (*) More opinions > > So, yeah, the idea of a course like that is to try to simplify the world > to students, but it totally backfires in my opinion. There is so much > syntax to learn, so many little details... We spend the entire semester > discussing these little details. Agreed, and if you try to teach all the syntax, you're inevitably going to get bogged down like that. > I posted here recently a study of the semantics of slices. When I > finally got it, I concluded it's not very simple. The course introduces > a few examples and expects students to get it all from these examples. > I would rather not introduce slices but teach students enough to write > procedures that give them the slices. The slices are the fish; learning > to write the procedures is the know-how. (I'm fine with even teaching > them how to write procedures to add or subtract numbers [and the rest of > arithmetic], although none of them would find mysterious what is the > meaning of arithmetic expressions such as 3 + 6 - 9, even taking > precedence of operators into account. That's syntax they already know. > If we teach them the syntax of procedures, we could be essentially done > with syntax.) A language like Python is useful, not because every tiny part of it is easy to explain, but because the language *as a whole* does what is expected of it. Toy languages are a lot easier to explain on a concrete level (look up Brainf*ck - it has very few operations and each one can be very simply defined), and that might be tempting in terms of "hey, we can teach the entire language in ten minutes", but they're utterly useless for students. Instead, my recommendation would be: Entice students with power. Pretend you're teaching some aspect of magic at a wizards' school and make sure your students feel massively OP. Sure, they might not understand what makes those cantrips work, but they know that they DO work. You can have students casting print calls left and right, doing complex incantations with list comprehensions, and even defining their own classes, all without ever worrying about the details of how it all works. Then once the "wow" is achieved, you can delve into the details of how things actually function, transforming progressively from "wizardry" to "science". And to be quite frank, a lot of code IS magic to most programmers. Which isn't a problem. Do you REALLY need to understand how your CPU does register renaming in order to benefit from it? Or do you need to know every detail of the TCP packet header before using the internet? Not likely. Those details hide away under the covers, and we make happy use of them. There's infinite knowledge out there, and you - and your students - are free to dip into exactly as much as you're comfortable with. ChrisA From rosuav at gmail.com Tue Aug 10 15:24:20 2021 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 11 Aug 2021 05:24:20 +1000 Subject: some problems for an introductory python test In-Reply-To: <86lf599zse.fsf@jevedi.xotimo> References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86lf599zse.fsf@jevedi.xotimo> Message-ID: On Wed, Aug 11, 2021 at 4:18 AM Hope Rouselle wrote: > > Chris Angelico writes: > > [...] > > >> not disagreeing... and yeah I could have thought deeper about the > >> answer, but I still think "notthing has been OOP" -> "yes it has, they > >> just didn't realize it" was worth mentioning > > > > Oh yes, absolutely agree. > > At the same time, inside the machine nothing is OOP --- so all the OOP > is no OOP at all and they just didn't realize it? This seems to show > that OOP is about perspective. An essential thing for OOP is the > keeping of states. Closures can keep state, so having procedures as > first-class values allows us to say we are doing OOP too. (Arguments of > procedures are messages and function application is message passing, > with closures keeping a state --- and all the rest of OOP can be > implemented with enough such functional technology.) In summary, OOP > should not be defined as some special syntax, otherwise there is no OOP > in ``2 + 2''. > > Having said that, I totally agree with all the nitpicking. Object orientation is a particular abstraction concept. It's not a feature of the machine, it's a feature of the language that you write your source code in. I've done OOP using IDL and CORBA, writing my code in C and able to subclass someone else's code that might have been written in some other language. [1] Central tenets of OOP (polymorphism, inheritance, etc) can be implemented at a lower level using whatever makes sense, but *at the level that you're writing*, they exist, and are useful. Data types, variables, control flow, these are all abstractions. But they're such useful abstractions that we prefer to think that way in our code. So, *to us*, those are features of our code. To the computer, of course, they're just text that gets processed into actually-executable code, but that's not a problem. So I would say that (in Python) there IS object orientation in "2 + 2", and even in the Python C API, there is object orientation, despite C not normally being considered an object-oriented language. ChrisA [1] And boy oh boy was that good fun. The OS/2 Presentation Manager had a wealth of power available. Good times, sad that's history now. From tjreedy at udel.edu Tue Aug 10 15:41:35 2021 From: tjreedy at udel.edu (Terry Reedy) Date: Tue, 10 Aug 2021 15:41:35 -0400 Subject: some problems for an introductory python test In-Reply-To: <86sfzha1ac.fsf@jevedi.xotimo> References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86sfzha1ac.fsf@jevedi.xotimo> Message-ID: On 8/10/2021 9:15 AM, Hope Rouselle wrote: >>>> 2.__add__(3) > SyntaxError: invalid syntax > > But then I tried: > >>>> (2).__add__(3) > 5 Add a space is easier. >>> 2 .__add__(3) 5 >>> -- Terry Jan Reedy From barry at barrys-emacs.org Tue Aug 10 17:00:14 2021 From: barry at barrys-emacs.org (Barry) Date: Tue, 10 Aug 2021 22:00:14 +0100 Subject: annotations cause dataclass fields type side effects In-Reply-To: References: Message-ID: > On 9 Aug 2021, at 19:28, Lukas L?sche wrote: > > ?I'm on Python 3.9.6 and trying to make sense of the following behaviour: > >>>> from dataclasses import dataclass, fields >>>> @dataclass > ... class Foobar: > ... name: str > ... >>>> fields(Foobar)[0].type > >>>> type(fields(Foobar)[0].type) > > > > >>>> from __future__ import annotations >>>> from dataclasses import dataclass, fields >>>> >>>> @dataclass > ... class Foobar: > ... name: str > ... >>>> fields(Foobar)[0].type > 'str' >>>> type(fields(Foobar)[0].type) > > > I have a validation function that checks if the types of all fields in > a dataclass are what they are supposed to be. But as soon as I import > annotations from __future__ this validation breaks as the arg that I'm > passing to isinstance() is no longer a type class but a string. > > What am I doing wrong? Nothing. As I understand the current situation you have to check if it?s a string and convert to the object you need at the moment. Hopefully someone with a deeper understanding will explain how you do this. I would guess use eval. This is a known problem and there are core devs that are working on improvements. But it will be at leas python 3.11 before there is a possible improvement. Barry > > Thanks, > -- Lukas > -- > https://mail.python.org/mailman/listinfo/python-list > From hrouselle at jevedi.com Tue Aug 10 17:13:58 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Tue, 10 Aug 2021 18:13:58 -0300 Subject: some problems for an introductory python test References: <868s1acoo1.fsf@jevedi.xotimo> <868s19bh70.fsf@jevedi.xotimo> Message-ID: <867dgtc8a1.fsf@jevedi.com> Chris Angelico writes: > On Wed, Aug 11, 2021 at 4:14 AM Hope Rouselle wrote: >> >> Chris Angelico writes: >> >> > On Tue, Aug 10, 2021 at 7:25 AM Hope Rouselle >> > wrote: >> >> I came up with the following question. Using strings of length 5 >> >> (always), write a procedure histogram(s) that consumes a string and >> >> produces a dictionary whose keys are each substrings (of the string) of >> >> length 1 and their corresponding values are the number of times each >> >> such substrings appear. For example, histogram("aaaaa") = {"a": 5}. >> >> Students can "loop through" the string by writing out s[0], s[1], s[2], >> >> s[3], s[4]. >> > >> > In other words, recreate collections.Counter? Seems decent, but you'll >> > need to decide whether you want them to use defaultdict, use >> > __missing__, or do it all manually. >> >> Yes, the course introduces very little so there is a lot of recreation >> going on. Hm, I don't know defaultdict and I don't know how to use >> __missing__. The course does introduce dict.get(), though. If students >> use dict.get(), then the procedure could essentially be: >> >> def histogram(s): >> d = {} >> d[s[0]] = d.get(s[0], 0) + 1 >> d[s[1]] = d.get(s[1], 0) + 1 >> d[s[2]] = d.get(s[2], 0) + 1 >> d[s[3]] = d.get(s[3], 0) + 1 >> d[s[4]] = d.get(s[4], 0) + 1 >> return d > > There's nothing wrong with getting students to recreate things, but > there are so many different levels on which you could do this, which > will leave your more advanced students wondering what's legal. :) Here > are several ways to do the same thing: [... very impressive set of solutions...] > It seems *very* strange to have an exercise like this without looping. It is. I agree. > That seems counterproductive. It is. > But if you're expecting them to not use loops, you'll want to also be > very clear about what other features they're allowed to use - or > alternatively, stipulate what they ARE allowed to use, eg "Use only > indexing and the get() method". Yes, I will do that. I mean the course does that all the time. They cannot use anything that has not been introduced. That's another problem because the course introduces various things and students can't quite keep everything in mind. The suggestion to make up a list of things is mostly ignored by nearly all of them. :-) From hrouselle at jevedi.com Tue Aug 10 17:27:15 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Tue, 10 Aug 2021 18:27:15 -0300 Subject: some problems for an introductory python test References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86sfzha1ac.fsf@jevedi.xotimo> Message-ID: <861r71c7nw.fsf@jevedi.com> Terry Reedy writes: > On 8/10/2021 9:15 AM, Hope Rouselle wrote: >>>>> 2.__add__(3) >> SyntaxError: invalid syntax >> But then I tried: >> >>>>> (2).__add__(3) >> 5 > > Add a space is easier. >>>> 2 .__add__(3) > 5 >>>> Hah. That's brilliant! So cool. From PythonList at DancesWithMice.info Tue Aug 10 19:30:00 2021 From: PythonList at DancesWithMice.info (dn) Date: Wed, 11 Aug 2021 11:30:00 +1200 Subject: on slices, negative indices, which are the equivalent procedures? In-Reply-To: <86sfznhk1f.fsf@example.com> References: <86sfznhk1f.fsf@example.com> Message-ID: Apologies for lateness. Coincidentally, I've been asked to speak to our local Python Users' Group on slicing. Herewith an attempt to modify those demos around your data/question. Apologies if the result is thus somewhat lacking in flow. Also, whereas I prefer to illustrate 'how it works', I perceive that you are used to learning 'rules' and only thereafter their application (the teaching-practice under which most of us learned) - so, another reason for mixing-things-up, to suit yourself (hopefully). TLDR; if you are a Python-Master there's unlikely to be anything here for you. However, if you have the time, I would appreciate any and all suggestions for improvement and correction. Please feel free to send off-list, should you prefer... As mentioned, the base-material (with different examples) is for a talk. However, I should reserve the right to turn it into an article (in my spare-time - a concept which could spawn a lengthy list-discussion on its own!). On 06/08/2021 05.35, Jack Brandom wrote: > The FAQ at > > https://docs.python.org/3/faq/programming.html#what-s-a-negative-index > > makes me think that I can always replace negative indices with positive > ones --- even in slices, although the FAQ seems not to say anything > about slices. Yes, it can be done. There's (much, much) more to the docs than the FAQ! > With slices, it doesn't seem to always work. For instance, I can > reverse a "Jack" this way: > >>>> s = "Jack Brandom" >>>> s[3 : -13 : -1] > 'kcaJ' > > I have no idea how to replace that -13 with a positive index. Is it > possible at all? Yes it is - but read on, gentle reader... If we envisage a string: - a positive index enables the identification of characters, from left-to-right - a negative index 'counts' from right-to-left, ie it takes the right-most elements/characters. The length of a string (sequence) is defined as len( str ). Accordingly, there is a formula which can 'translate' the length and either statement of the index's relative-location, to the other. To quote one of the web.refs (offered below) "If i or j is negative, the index is relative to the end of sequence s: len(s) + i or len(s) + j is substituted. But note that -0 is still 0." Clear as mud? Please continue... > But this example gives me the idea that perhaps each slice is equivalent > to a certain loop (which I could write in a procedure). So I'm looking > for these procedures. If I can have the procedures in mind, I think I > will be able to undersand slices without getting surprised. > > Do you have these procedures from the top of your mind? While I haven't > given up yet, I am not getting too close. Thank you! Us Silver-Surfers have to stick-together. So, let's try closing the gap. Rather than attempting to re-build Python, perhaps some experimenting with sequences, indexing, and slicing is what is required? I can see writing a simulation routine as a perfectly-valid (proof of) learning-approach - and one we often applied 'back then'. However, is it the 'best' approach? (Only you can judge!) I would fear that the effort (and perhaps frustration) of attempting to code slicing manually may add coding-problems to the mix, and start to erect a 'brick wall' or a 'greasy slope', in grand Sisyphian tradition. In attempting to learn two things at the same time, are you gambling against the old advice about "never take (only) two chronometers to sea"? ie when things don't work, is the error in the code, in the implementation of slicing, or in one's understanding/learning of slicing??? Another, word-of-warning from an 'old hand': don't try to make Python look like some 'previous language'. Similarly, just because it looks similar doesn't mean Python will work the same way as xyz-language! Enough with the philosophy, diving right in:- "Subscription" is the process of selecting an item from a sequence. Thus, an index is a means of locating/evaluating a single item within a sequence, eg 0 locates the "J" within "Jack": >>> "Jack"[ 0 ] 'J' Python offers several "built-in" sequences: strings, lists, tuples, bytes, bytearrays, and ranges. May I take it that you have at least a basic understanding of the first three? - more about ranges later... Your examples have been strings, and that's a good application for (and illustration of) slices (aka "sub-strings"). So, we'll stick with them. However, the behaviors are replicated in other sequence-structures - albeit with perhaps fewer real-world applications. Python has other built-in collections. Sets do not index their elements, by definition; and although "mappings"/dicts do use a form of subscripting (which need not be numeric), they cannot be sliced. Similarly, namedtuples (which offer both forms of subscripting). Accordingly, they have been ignored for today's purposes. It is worth noting though, advanced-users coding an aggregate custom-class, can add indexing and slicing capabilities by coding a __getitem__() method. A Python "container" is designed to 'hold' other data-items ("by reference"). To be called a "sequence", the container-class must implement the __getitem__ 'magic method'/"dunder-method". If you haven't studied these, now is not the time, but they are a topic worth adding to the ToDo list... Unlike other languages and their 'array' structures, Python has no rule limiting a "container", "collection", or "sequence" to contain data-items of an uniform type ("homogenous"). Accordingly, mixing int[eger]s, floats, strings, etc, and even other collections within a single container, is not only possible but common-practice. As you've noticed, an index may be expressed as a positive (more accurately: a non-negative) integer - counting from the left; or a negative-integer - off-set from, or relative-to, the 'end' of the sequence. Applying an index to a sequence (as an offset, as we used to say) will realise a single element, of whatever type. So, we might describe the index as a 'pointer' into the sequence. Whereas, a slice is a sub-sequence. It will always be of the same type as the original sequence, and it 'contained' element(s) type(s) will not be changed, eg taking "Jack" from "Jack Brandom" produces a (sub-)string from a string. It does not help matters when indexing and slicing are of described in-writing as: index: sequence[ i ] slice: sequence[ i, j ] stride: sequence[ i, j, k ] This fails to show the differences in conceptual view. Indeed, technically, a "stride" is only the (optional) "k" component of a slice. Further, many authors gather-up the three terms into "slicing", which equally fails to help in bending one's mind around the similarities and differences! Thus, an index is merely a subscript, but a slice is a sequence (cf a couple of integers). A bit of a diversion (but worth reviewing later if you insist on jumping to 'the good stuff' right now)... In Python, the saying goes, everything is an object. Sure-enough "slice" is also the name of an object: class slice(stop) or class slice(start, stop[, step]) "...representing the set of indices specified by range(start, stop, step)... Slice objects are also generated when extended indexing syntax is used." Notice how the class name of "slice" is not compatible with the docs definition - but is part of a mechanism to get there. Mention of "range" introduces another Python built-in object - and keep in mind that it is a "sequence": class range(stop) or class range(start, stop[, step]) "range is actually an immutable sequence type" NB since Python 3 range() implements a generator. If you ever need to debug-print a range, first convert it to a list, ie list( range (...) ). Slice and Range objects seem the same, don't they? Many authors confuse the two, and it doesn't help that we'd like to describe the 'width' or 'size' of a slice as its "range" (English-language definition). However, Slice and Range objects have distinctly different purposes: >>> sl = slice( 1, 2 ) >>> sl slice(1, 2, None) >>> rg = range( 1, 2 ) >>> rg range(1, 2) >>> list( sl ) Traceback (most recent call last): File "", line 1, in TypeError: 'slice' object is not iterable >>> list( rg ) [1] >>> "Jack"[ sl ] 'a' >>> "Jack"[ rg ] Traceback (most recent call last): File "", line 1, in TypeError: string indices must be integers >>> for i in sl: print( i ) ... Traceback (most recent call last): File "", line 1, in TypeError: 'slice' object is not iterable >>> for i in rg: print( i ) ... 1 So, they look the same, they sound the same, but they are not the same (cf "Duck Typing"). A slice object is not iterable, so it can't be converted into a list, nor used to control a for-loop. Whereas a range object can do those things, but won't slice a sequence. Hence the expression, to either "fish or cut bait"! NB Python describes slice objects as an "Internal type". Which means that they are "used internally by the interpreter [and] are exposed to the user". The corollary to such, is that they are subject to change at the whim of the 'Python gods'. Explicit use of slice-objects is unusual. However, it may be helpful in situations where the slice is defined programmatically. Another opportunity might be to self-document some 'business rule', eg if instead of a name we were manipulating Olympics event-results to determine Gold, Silver, and Bronze medal-winners: >>> first_three = slice( 0, 3 ) >>> name[ first_three ] 'Jac' Not clear? If the operative sequence were [ 'Fred', 'Wilma', 'Barney', 'Betty' ] then the medal-winner's names will be identified. At this point, an apropos reminder is that a Python for-loop is not the same as similar constructs appearing in some other languages, eg a FORTRAN DO-loop. Python's "for" should be read as "for-each" and must be 'fed' an iterable-object, eg a sequence. The 'old way' involved a range (expression, or object) and was prone to ye olde "out by one" error: >>> for letter in "Jack": ... print( letter, end=" " ) ... J a c k >>> for index in range( len( "Jack" ) ): ... print( "Jack"[ index ], end=" " ) ... J a c k Substituting an identical range-object in the for-expression: >>> for_range = range( len( "Jack" ) ) >>> for_range range(0, 4) >>> for index in for_range: ... print( "Jack"[ index ], end=" " ) ... J a c k ...and to really 'push the boat out' we could employ an "assignment expression", aka "the walrus operator" (v3.8+): >>> for_range = range( len( string:="Jack" ) ) >>> for_range range(0, 4) >>> string 'Jack' >>> for index in for_range: ... print( string[ index ], end=" " ) ... J a c k NB @Chris has a firm-rule that one may only use the Walrus-operator whilst smiling-widely and baring your teeth! Lesson: for-each is so much shorter to express, and there's no possibility of under- or over-stating the 'start' and 'end' values which range requires (possibly THE most common coding-error whilst using other languages). Getting back on-track: A slice is *not* made-up of one, two, or three indexes/indices* (the rest implied), no matter the appearance of its definition! * yes, some of us were schooled in Latin and/or English-English. No apology offered/expected/implied/needed! This only (starts to) makes sense once all the definitions/rules, defaults, and conventions, are understood:- Start by defining an index. The work 'up' to slices. An index "i" may hold a zero-, positive-, or negative-value, according to the following rules: 0 <= i < len( sequence ) -len( sequence ) <= i < 0 i is of type int[eger] So, zero-based off-set, or "origin". Thus: >>> "Jack"[ 9 ] Traceback (most recent call last): File "", line 1, in IndexError: string index out of range >>> "Jack"[ 2.3 ] :1: SyntaxWarning: str indices must be integers or slices, not float; perhaps you missed a comma? Traceback (most recent call last): File "", line 1, in TypeError: string indices must be integers NB same problem, and similar wording in final err.msg, for all the other built-in sequences. You were asking about the mapping between positive and negative indexes/indices. Please note that such terminology implies that zero is a positive-value. It isn't - but what's a little 'fudging' between friends? For "Jack" the positive index sequence is: 0, 1, 2, 3 J ~ 0 a ~ 1 c ~ 2 k ~ 3 whereas the negative-index sequence is: -4, -3, -2, -1 J ~ -4 a ~ -3 c ~ -2 k ~ -1 (if this is not visually-obvious, try re-writing the above sequences on grid-/squared-paper, or using worksheet software) Alternately, (with apologies for 'cheating') this may be some help: >>> print( " Pos Ltr Neg" ) >>> print( " ndx ndx" ) >>> for positive_index, character, negative_index in zip( range( 12 ), name, range( -12, 0 ) ): ... print( f"{ positive_index:4} { character } { negative_index:4}" ) Pos Ltr Neg ndx ndx 0 J -12 1 a -11 2 c -10 3 k -9 4 -8 5 B -7 6 r -6 7 a -5 8 n -4 9 d -3 10 o -2 11 m -1 Again, please note the lack of zero amongst the negative indexing, whereas positive-indexes/indices are "zero-based"! (I have prepared some schematics to better illustrate the relationships between an index and the element it identifies, but regret that graphics cannot be attached to list-posts) Another reason why folk have difficulty with using an index or offset is the subtle difference between "cardinal" and "ordinal" numbers. Cardinal numbers are for counting, eg the number of letters in the name. Whereas, ordinal numbers refer to a position, eg first, second, third... (there are also "nominal numbers" which are simply labels, eg Channel 3 TV - but we're not concerned with them). There is an implicit problem in that Python uses zero-based indexing, whereas spoken language starts with a word like "first" or "1st" which looks and sounds more like "one" than "zero". Despite it being a junior-school 'math' topic, it is easy to fail to recognise which of the two types of number is in-use. The len( sequence ) provides a cardinal number. An index is an ordinal number. Using the "rules" (above) and transforming around len( "Jack" ), one arrives at suitable 'translation' formulae/formulas: negative-index = -1 * ( len( sequence ) - positive-index ) positive-index = len( sequence ) + negative-index Remembering that -0 == 0 == +0, also that whilst the examples (above) use simple-values (literal or single variable) for the index, in real-life an index may be an expression (and often is the result of some calculation)! The above rules describing an index do not apply to a slice's "start", "stop", or "step" values! The documentation expresses: proper_slice ::= [lower_bound] ":" [upper_bound] [ ":" [stride] ] lower_bound ::= expression upper_bound ::= expression stride ::= expression Elsewhere in the docs the rules are described using to i, j, and k. NB in this context "k" is not the "stride"! Thus: "The slice of s from i to j is defined as the sequence of items with index k such that i <= k < j. If i or j is greater than len(s), use len(s). If i is omitted or None, use 0. If j is omitted or None, use len(s). If i is greater than or equal to j, the slice is empty." Note how there are default-values to cover omissions and how under-/over-runs are treated. Remember: neither the element sequence[ j ] (if it exists) nor sequence[ len( sequence ) ] will be included within the slice. Lesson: Whereas some like to talk of ( start:stop:step ), it might be more helpful to verbalise the relationships as "starting at:" and "stopping before"! Diversion:- If you have a math-background and are familiar with such tools as "Intervals", note that a Python slice is a closed-open interval, ie includes the first end-point (index) but excludes the 'upper' end-point. In comparison to set-notation (as above), Interval notation defines a Python slice as: [ i, j ) Interval notation may also be useful to your comprehension because its view of negative- and positive-infinity, which as defaults or 'corrections' apply to slices as index-0 and len( sequence ), respectively. NB Intervals are usually described as a segment of a real number line. Whereas, Python's slices are defined by integers. Future demos (below) will use: >>> name = "Jack Brandom" >>> len( name ) 12 >>> name[ 0:12 ] 'Jack Brandom' In slices, the "lower_bound" is optional. If it is missing it is taken to be None. For now we can probably 'get away with' calling it 0, ie 'the first item in the sequence'. >>> name[ :6 ] 'Jack B' The "upper_bound is also optional. If it is missing it is also taken to be None, but this defaults to 'the last item in the sequence'. >>> name[ 5: ] 'Brandom' Interestingly both may be left-out: >>> name[ : ] 'Jack Brandom' >>> name[ : ] == name True - which is a handy way to make a copy of a sequence - but "shallow-copy" and "deep-copy" considerations are a separate conversation. (another topic for the ToDo list...) The "stride" is also optional. If it is missing, it's None-value is taken to be int( 1 ). (as seen above) >>> name[ :: ] 'Jack Brandom' A stride may not be int( 0 ). Many people consider the "stride"/step to indicate a sub-selection of elements from within the slice's defined extent. However, it may be more helpful to consider the r?le of the stride as defining the 'direction' in which elements will be selected (per 'reverse') - and thereafter its 'step effect'. Back when Python 2.4 was released, "PEP 322: Reverse Iteration" observed "Compared to extended slicing, such as range(1,4)[::-1], reversed() is easier to read, runs faster, and uses substantially less memory." - and that even when the same release included optimisations for list and tuple slicing. NB I have no reference to say that such is still true in Python 3.9. The reality is that the stride is rarely used in professional programs/programmes - but given that enquiring-minds want to know, please read on... Here's how to take every-other item (every second item): >>> name[ : :2 ] 'Jc rno' This was originally used in one of the few 'real-world' examples I've noted. The routine's incoming-data is the output taken from a data-logger (which is only picked-up periodically, ie in a "batch"). The device(s) measure the depth of a river or reservoir. The data presents as a series of data-points which are to be considered in pairs - the first value is a datetime and the second a depth measurement. Accordingly, splitting the data was facilitated by slicing: reading_times = batch_data[ : :2 ] depths_recorded = batch_data[ 1: :2 ] Thereafter the two lists could be zipped (another for the ToDo list?) and processed (in pairs) along a time-line. Please note the use of a list-sequence: batch_data (cf most of the examples here being string-sequences). The blank (None) upper-bound meant that knowing the size of the batch (depending upon how frequently someone 'read the meter') was conveniently irrelevant! Indeed being able to calculate len( depths ) is more practical. >From the docs, the formula for striding is: "The slice of s from i to j with step k is defined as the sequence of items with index x = i + n*k such that 0 <= n < (j-i)/k. In other words, the indices are i, i+k, i+2*k, i+3*k and so on, stopping when j is reached (but never including j). When k is positive, i and j are reduced to len(s) if they are greater. When k is negative, i and j are reduced to len(s) - 1 if they are greater. If i or j are omitted or None, they become ?end? values (which end depends on the sign of k). Note, k cannot be zero. If k is None, it is treated like 1." Wow, what a mouthful! No wonder many of us fail to grasp it all, first time. Remembering the rules governing indexes/indices, be advised that these do not apply to either the lower_bound or the upper_bound of a slice. For example: >>> name[ +100 ] Traceback (most recent call last): File "", line 1, in IndexError: string index out of range and: >>> name[ -100 ] Traceback (most recent call last): File "", line 1, in IndexError: string index out of range yet: >>> name[ -100:+100 ] 'Jack Brandom' Just as a "lower_bound" of 0 or None is taken to mean the first item in the sequence, so any ludicrous value is also 'translated'. Similarly, despite knowing the length (of the example-data) is 12, a slice's upper-bound that evaluates to a larger number will be 'rounded down'. So, some good news when calculating slices, is that precise subscripting may not be required! However, each of the three arguments present must evaluate to an integer-value (per similar index rule). Something (else) to think about: where i == j (or start == stop), the result may not be obvious: >>> name[ 3:3 ] '' >>> name[ -6:-6 ] '' This can be explained by referring back to the closed-open characteristic and that the "stop" element is not to be included! Whereas no default value exists when evaluating an index, default-values are allowed in slices. However, don't take things too far: >>> name[] File "", line 1 name[] ^ SyntaxError: invalid syntax Also, per discussion of positive- and negative-indexing, slices can also be expressed using 'positive' or negative bounds, and "stride", eg extracting the given-name: >>> name[ :4 ] 'Jack' >>> name[ :-8 ] 'Jack' Notice that in the second example, the 'upper_bound' might not appear to be greater than the 'lower_bound'! The tricks differ if the 'target' is the family-name: >>> name[ 5: ] 'Brandom' >>> name[ -7: ] 'Brandom' but to demonstrate with some non-default "bounds", (if you'll permit the (weak-)humor - and with no insult intended to your good name) we could describe distaste for a popular breakfast cereal (All Bran?): >>> name[ 1:9 ] 'ack Bran' >>> name[ -11:-3 ] 'ack Bran' The 'translation formula' between the 'positive' and 'negative' forms of the expressions applies here too! We can put 'you' into reverse by using a negative-stride: >>> name[ 4::-1 ] ' kcaJ' >>> name[ -8::-1 ] ' kcaJ' Oops! (not that the reversed-name is preceded by an unwanted space-character) The reverse direction requires a re-think of the lower-bound value we were using (above) and may necessitate a review of the schematics presented earlier, in conjunction with the closed-open convention: >>> name[ 4-1::-1 ] 'kcaJ' >>> name[ -8-1::-1 ] 'kcaJ' >>> name[ :4:-1 ] 'modnarB' >>> name[ :-8:-1 ] 'modnarB' name[ 6:2:-1 ] 'rB k' >>> name[ -6:-10:-1 ] 'rB k' Whilst some re-thinking is taking-place, what will be the result of asking: name[ -2:-1 ]? It will not give the last two elements/characters of your name - as might be expected. Here's another example of the out-by-one error and Python's inclusive-exclusive/half-open intervals: >>> name[ -2:-1 ] 'o' Similarly: >>> name[ -1:-3:-1 ] 'mo' Going for the hat-trick? Here's even more opportunity for some head-scratching: >>> name[ :-2:-2 ] 'm' What is rather handy, is that using a negative (unity) stride has the effect of reversing the string (sequence): >>> name[ ::-1 ] 'modnarB kcaJ' In case it passed unnoticed, when using a negative-stride, the default-values for 'missing' lower- and upper-bounds change too. The lower-bound defaults to -1, and the upper-bound to -len( sequence ) - 1! Those of us who have worked with earlier/lower-'level' languages can usually take to zero-based subscripting without thought. However, the exclusion of an upper-bound might take a bit more getting used-to. (the above 'fiddling' of +1 or -1 reminded me very much of FORTRAN contortions!) Thus, when we look at negative indexes/indices we may well feel shades of those ?bad, old days! Here's another thought-provoker: >>> name[ :4 ] + name[ 4: ] 'Jack Brandom' It only works because of the 'closed-open' characteristic! To round things out, here's some 'theory':- Contrary to practice, the Python Reference Manual (6.3.3 Slicings) says: <<< The formal syntax makes no special provision for negative indices in sequences; however, built-in sequences all provide a __getitem__() method that interprets negative indices by adding the length of the sequence to the index (so that x[-1] selects the last item of x). The resulting value must be a nonnegative integer less than the number of items in the sequence, and the subscription selects the item whose index is that value (counting from zero). Since the support for negative indices and slicing occurs in the object?s __getitem__() method, subclasses overriding this method will need to explicitly add that support. >>> This seems consistent with the comment about Slice classes being internal constructs. Remember (from earlier) that custom-classes and the __getitem__() method were put-aside as 'advanced topics', and not for today's discussion! Worse, discussing Sequences (3.2. The standard type hierarchy) the Data Model says: <<< These represent finite ordered sets indexed by non-negative numbers. The built-in function len() returns the number of items of a sequence. When the length of a sequence is n, the index set contains the numbers 0, 1, ?, n-1. Item i of sequence a is selected by a[i]. Sequences also support slicing: a[i:j] selects all items with index k such that i <= k < j. When used as an expression, a slice is a sequence of the same type. This implies that the index set is renumbered so that it starts at 0. Some sequences also support ?extended slicing? with a third ?step? parameter: a[i:j:k] selects all items of a with index x where x = i + n*k, n >= 0 and i <= x < j. >>> So, now there is yet more alternate nomenclature for 'stride'. Plus there is no mention of negative-values for index or bound! For completeness: - the above exclusively discusses using slices to 'get' data - what we used to term "RHS", ie usage on the Right-Hand Side of an assignment. An expression may involve an index or slice on the LHS, if (and only if) the target-sequence is mutable (eg lists, but not strings or tuples). - slices and subscriptions can be used in a del statement, but exactly what this means "is determined by the sliced object". (these are also topics for another day) Finally, it is not forgotten that you want to code a loop which simulates a slice with negative attributes. (although it is hoped that after the above explanations (and further reading) such has become unnecessary as a learning-exercise!) Please recall that whilst a slice-object will not, a range-object will work with a for-loop. So: >>> rng = range( 4, 0, -1 ) >>> list( rng ) [4, 3, 2, 1] >>> for index in rng: ... print( name[ index ], end=" " ) ... k c a >>> Oops! This looks familiar, so apply the same 'solution': >>> rng = range( 4, -1, -1 ) >>> list( rng ) [4, 3, 2, 1, 0] >>> for index in rng: ... print( name[ index ], end=" " ) ... k c a J The 'bottom line' is that such simulation code will become torturous simply because indexes/indices follow different rules to slices! Should you wish to persist, then may I suggest modifying mySlice(it, beg, end, step = 1) to: def my_slice( sequence, lower_bound, upper_bound, stride=1 ): and first splitting the implementation's decision-tree into two paths, according to whether the stride is positive or negative, before getting into 'the nitty-gritty'. Perversely (if not, foolishly) I have indulged (and can't recommend it!). Nevertheless, if you are determined, I will be happy to forward some test conditions, upon request (caveat emptor!)... Web.Refs/Further reading: https://docs.python.org/3/tutorial/introduction.html https://docs.python.org/3/reference/expressions.html#primaries https://docs.python.org/3/library/functions.html https://docs.python.org/3/tutorial/controlflow.html https://docs.python.org/3/library/stdtypes.html#typesseq https://docs.python.org/3/library/stdtypes.html#ranges https://docs.python.org/3/reference/simple_stmts.html https://docs.python.org/3/glossary.html https://web.archive.org/web/20190321101606/https://plus.google.com/115212051037621986145/posts/YTUxbXYZyfi https://docs.python.org/3/reference/datamodel.html -- Regards, =dn From tjreedy at udel.edu Tue Aug 10 23:22:43 2021 From: tjreedy at udel.edu (Terry Reedy) Date: Tue, 10 Aug 2021 23:22:43 -0400 Subject: some problems for an introductory python test In-Reply-To: <861r71c7nw.fsf@jevedi.com> References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86sfzha1ac.fsf@jevedi.xotimo> <861r71c7nw.fsf@jevedi.com> Message-ID: On 8/10/2021 5:27 PM, Hope Rouselle wrote: > Terry Reedy writes: > >> On 8/10/2021 9:15 AM, Hope Rouselle wrote: >>>>>> 2.__add__(3) >>> SyntaxError: invalid syntax >>> But then I tried: >>> >>>>>> (2).__add__(3) >>> 5 >> >> Add a space is easier. >>>>> 2 .__add__(3) >> 5 >>>>> > > Hah. That's brilliant! So cool. Python is a little looser about whitespace than one might expect from reading 'normal' code when the result is unambiguous in that it cannot really mean anything other than what it does. Two other examples: >>> if3: print('yes!') yes! >>> [0] [0] 0 -- Terry Jan Reedy From wolfram.hinderer at googlemail.com Wed Aug 11 13:10:27 2021 From: wolfram.hinderer at googlemail.com (Wolfram Hinderer) Date: Wed, 11 Aug 2021 19:10:27 +0200 Subject: some problems for an introductory python test In-Reply-To: References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86sfzha1ac.fsf@jevedi.xotimo> <861r71c7nw.fsf@jevedi.com> Message-ID: <30ad3e32-c7f5-e255-4c18-0147a56c3346@gmail.com> Am 11.08.2021 um 05:22 schrieb Terry Reedy: > Python is a little looser about whitespace than one might expect from > reading 'normal' code when the result is unambiguous in that it cannot > really mean anything other than what it does.? Two other examples: > > >>> if3: print('yes!') > yes! > >>> [0]? [0] > 0 Not sure what you mean here - is it a joke? The first looks like an if statement, but isn't. The missing space *does* make a difference. (Try "if0" instead.) The second is normal indexing, which allows white space. I wouldn't consider that surprising, but maybe I should? (Honest question, I really don't know.) -- Wolfram Hinderer From python at mrabarnett.plus.com Wed Aug 11 14:10:24 2021 From: python at mrabarnett.plus.com (MRAB) Date: Wed, 11 Aug 2021 19:10:24 +0100 Subject: some problems for an introductory python test In-Reply-To: <30ad3e32-c7f5-e255-4c18-0147a56c3346@gmail.com> References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86sfzha1ac.fsf@jevedi.xotimo> <861r71c7nw.fsf@jevedi.com> <30ad3e32-c7f5-e255-4c18-0147a56c3346@gmail.com> Message-ID: <6382edc7-ac3f-7b7b-a183-c109f9fb5b8b@mrabarnett.plus.com> On 2021-08-11 18:10, Wolfram Hinderer via Python-list wrote: > > > Am 11.08.2021 um 05:22 schrieb Terry Reedy: >> Python is a little looser about whitespace than one might expect from >> reading 'normal' code when the result is unambiguous in that it cannot >> really mean anything other than what it does.? Two other examples: >> >> >>> if3: print('yes!') >> yes! >> >>> [0]? [0] >> 0 > > Not sure what you mean here - is it a joke? The first looks like an if > statement, but isn't. The missing space *does* make a difference. (Try > "if0" instead.) > I see what you mean. It's a type annotation: var: type where the "type" is a print statement! > The second is normal indexing, which allows white space. I wouldn't > consider that surprising, but maybe I should? (Honest question, I really > don't know.) > From greg.ewing at canterbury.ac.nz Wed Aug 11 04:41:35 2021 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Wed, 11 Aug 2021 20:41:35 +1200 Subject: some problems for an introductory python test In-Reply-To: References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86sfzha1ac.fsf@jevedi.xotimo> <861r71c7nw.fsf@jevedi.com> Message-ID: On 11/08/21 3:22 pm, Terry Reedy wrote: > Python is a little looser about whitespace than one might expect from > reading 'normal' code when the result is unambiguous in that it cannot > really mean anything other than what it does. > > >>> if3: print('yes!') > yes! That may not be doing what you think it's doing. Consider also >>> if0: print('yes!') yes! -- Greg From hrouselle at jevedi.com Wed Aug 11 08:09:48 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Wed, 11 Aug 2021 09:09:48 -0300 Subject: some problems for an introductory python test References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86sfzha1ac.fsf@jevedi.xotimo> <861r71c7nw.fsf@jevedi.com> Message-ID: <86sfzgb2sz.fsf@jevedi.com> Terry Reedy writes: > On 8/10/2021 5:27 PM, Hope Rouselle wrote: >> Terry Reedy writes: >> >>> On 8/10/2021 9:15 AM, Hope Rouselle wrote: >>>>>>> 2.__add__(3) >>>> SyntaxError: invalid syntax >>>> But then I tried: >>>> >>>>>>> (2).__add__(3) >>>> 5 >>> >>> Add a space is easier. >>>>>> 2 .__add__(3) >>> 5 >>>>>> >> Hah. That's brilliant! So cool. > > Python is a little looser about whitespace than one might expect from > reading 'normal' code when the result is unambiguous in that it cannot > really mean anything other than what it does. Two other examples: > >>>> if3: print('yes!') > yes! That's cool to know too, but I would have expected that. Programming languages tend to ignore whitespace as much as possible. (But someone followed-up with more details... I'll get there.) But the next one... >>>> [0] [0] > 0 Oh! This almost fooled me. It's just a list containing the integer zero followed by the index-operator (or however the brackets are called in this case.) At first I thought maybe there was an implicit operator between lists just like it happens with strings. >>> "a" "," "b" 'a,b' But which operator would it be? It wasn't concatenation, of course. So I looked at what type() thought of it. Then I tried changing numbers: >>> [1] [1] Traceback (most recent call last): File "", line 1, in [1] [1] IndexError: list index out of range And that's when it hit me. :-) Thanks! From hrouselle at jevedi.com Wed Aug 11 08:11:33 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Wed, 11 Aug 2021 09:11:33 -0300 Subject: some problems for an introductory python test References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86sfzha1ac.fsf@jevedi.xotimo> <861r71c7nw.fsf@jevedi.com> Message-ID: <86mtpob2q2.fsf@jevedi.com> Greg Ewing writes: > On 11/08/21 3:22 pm, Terry Reedy wrote: >> Python is a little looser about whitespace than one might expect >> from reading 'normal' code when the result is unambiguous in that it >> cannot really mean anything other than what it does. >> >>> if3: print('yes!') >> yes! > > That may not be doing what you think it's doing. Consider also > >>>> if0: print('yes!') > yes! So, yes, that's puzzling. >>> 0 == False True >>> if0: print("yes") yes >>> if(0): print("yes") >>> What's going on there? From hrouselle at jevedi.com Wed Aug 11 08:27:38 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Wed, 11 Aug 2021 09:27:38 -0300 Subject: some problems for an introductory python test References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86sfzha1ac.fsf@jevedi.xotimo> Message-ID: <86czqkb1z9.fsf@jevedi.com> Chris Angelico writes: > On Wed, Aug 11, 2021 at 4:18 AM Hope Rouselle wrote: >> >> I totally agree with you but I didn't know that even numbers were like >> that in Python. In fact, I still don't quite believe it... >> >> >>> 2.__add__(3) >> SyntaxError: invalid syntax > > Yeah, that's because "2." looks like the beginning of a float. > >> But then I tried: >> >> >>> (2).__add__(3) >> 5 >> >> Now I do believe it! :-) Awesome. I had no idea. > > You can also do it this way: > >>>> x = 2 >>>> x.__add__(3) > 5 > > But don't teach this; it ignores several problems. I wouldn't. This is all Python-stuff. The course chooses a language like Python, but it is not trying to teach Python --- it is trying to teach computer programming, that is, strategies in high-precision. [...] >> (*) More opinions >> >> So, yeah, the idea of a course like that is to try to simplify the world >> to students, but it totally backfires in my opinion. There is so much >> syntax to learn, so many little details... We spend the entire semester >> discussing these little details. > > Agreed, and if you try to teach all the syntax, you're inevitably > going to get bogged down like that. Indeed. >> I posted here recently a study of the semantics of slices. When I >> finally got it, I concluded it's not very simple. The course introduces >> a few examples and expects students to get it all from these examples. >> I would rather not introduce slices but teach students enough to write >> procedures that give them the slices. The slices are the fish; learning >> to write the procedures is the know-how. (I'm fine with even teaching >> them how to write procedures to add or subtract numbers [and the rest of >> arithmetic], although none of them would find mysterious what is the >> meaning of arithmetic expressions such as 3 + 6 - 9, even taking >> precedence of operators into account. That's syntax they already know. >> If we teach them the syntax of procedures, we could be essentially done >> with syntax.) > > A language like Python is useful, not because every tiny part of it is > easy to explain, but because the language *as a whole* does what is > expected of it. Toy languages are a lot easier to explain on a > concrete level (look up Brainf*ck - it has very few operations and > each one can be very simply defined), and that might be tempting in > terms of "hey, we can teach the entire language in ten minutes", but > they're utterly useless for students. Sure. I would never use a toy language like that. I think we need a compromise --- some syntax, but not too much; in fact, just a little bit of syntax. For instance, could we do away with slices? We could. If we learn one way of looping, we can build slices with procedures. This is a good opportunity in fact --- it will show students how slices really work and how to get what they want with it. (Then towards the end we could give out a lecture for anyone interested in Python --- ``while we didn't show you how Pythonists usually write, here's a few things that Pythonists would do that we didn't do in this course...'') > Instead, my recommendation would be: Entice students with power. > Pretend you're teaching some aspect of magic at a wizards' school and > make sure your students feel massively OP. Sure, they might not > understand what makes those cantrips work, but they know that they DO > work. You can have students casting print calls left and right, doing > complex incantations with list comprehensions, and even defining their > own classes, all without ever worrying about the details of how it all > works. Then once the "wow" is achieved, you can delve into the details > of how things actually function, transforming progressively from > "wizardry" to "science". I really like that, but I would predict that, in a typical university, professors are not really willing to go that way. Everything has to be extremely simple --- and a mess is made in trying to achive that. (In a sense, professors are all failing terribly. They're lucky that nobody is giving them a grade based on how effective they are as evidenced by the facts, however such thing would be done in practice if one were to take it seriously.) > And to be quite frank, a lot of code IS magic to most programmers. Definitely. You guys are showing me so much Python here that I've never seen --- which I expect, because I'm only paying attention at Python now since I'm conducting students through a course that's using it. (I admire the language, but I never used it in any project on my own. I probably would if I were not in love with other similar technology.) > Which isn't a problem. Do you REALLY need to understand how your CPU > does register renaming in order to benefit from it? Or do you need to > know every detail of the TCP packet header before using the internet? > Not likely. Not at all. (Although, of course, we like to know these stuff.) > Those details hide away under the covers, and we make happy use of > them. There's infinite knowledge out there, and you - and your > students - are free to dip into exactly as much as you're comfortable > with. ``A man after my own heart.'' From hrouselle at jevedi.com Wed Aug 11 08:33:40 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Wed, 11 Aug 2021 09:33:40 -0300 Subject: some problems for an introductory python test References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86lf599zse.fsf@jevedi.xotimo> Message-ID: <868s18b1p7.fsf@jevedi.com> Chris Angelico writes: > On Wed, Aug 11, 2021 at 4:18 AM Hope Rouselle wrote: >> >> Chris Angelico writes: >> >> [...] >> >> >> not disagreeing... and yeah I could have thought deeper about the >> >> answer, but I still think "notthing has been OOP" -> "yes it has, they >> >> just didn't realize it" was worth mentioning >> > >> > Oh yes, absolutely agree. >> >> At the same time, inside the machine nothing is OOP --- so all the OOP >> is no OOP at all and they just didn't realize it? This seems to show >> that OOP is about perspective. An essential thing for OOP is the >> keeping of states. Closures can keep state, so having procedures as >> first-class values allows us to say we are doing OOP too. (Arguments of >> procedures are messages and function application is message passing, >> with closures keeping a state --- and all the rest of OOP can be >> implemented with enough such functional technology.) In summary, OOP >> should not be defined as some special syntax, otherwise there is no OOP >> in ``2 + 2''. >> >> Having said that, I totally agree with all the nitpicking. > > Object orientation is a particular abstraction concept. It's not a > feature of the machine, it's a feature of the language that you write > your source code in. I've done OOP using IDL and CORBA, writing my > code in C and able to subclass someone else's code that might have > been written in some other language. [1] Central tenets of OOP > (polymorphism, inheritance, etc) can be implemented at a lower level > using whatever makes sense, but *at the level that you're writing*, > they exist, and are useful. > > Data types, variables, control flow, these are all abstractions. But > they're such useful abstractions that we prefer to think that way in > our code. So, *to us*, those are features of our code. To the > computer, of course, they're just text that gets processed into > actually-executable code, but that's not a problem. Total agreement. > So I would say that (in Python) there IS object orientation in "2 + > 2", and even in the Python C API, there is object orientation, despite > C not normally being considered an object-oriented language. But would you say that 2 + 2 is also an illustration of object orientation in any other language too? Regarding C, I have many times said that myself. If I wrote assembly, I'm sure I would do my best to create things like procedures --- a label and some bureaucracy to get arguments in and a return value out. > ChrisA > > [1] And boy oh boy was that good fun. The OS/2 Presentation Manager > had a wealth of power available. Good times, sad that's history now. I know OS/2 only by name. I never had the pleasure of using it. In fact, I don't even know how it looks. I must be a little younger than you are. But not too younger because I kinda remember its name. Was it a system that might have thought of competing against Microsoft Windows? :-) That's what my memory tells me about it. From jbrandom at example.com Wed Aug 11 10:59:11 2021 From: jbrandom at example.com (Jack Brandom) Date: Wed, 11 Aug 2021 11:59:11 -0300 Subject: on slices, negative indices, which are the equivalent procedures? References: <86sfznhk1f.fsf@example.com> Message-ID: <86wnos9ge8.fsf@jevedi.com> dn writes: > Apologies for lateness. That's alright. Thanks for the marvelous post. > Coincidentally, I've been asked to speak to our local Python Users' > Group on slicing. Herewith an attempt to modify those demos around your > data/question. Apologies if the result is thus somewhat lacking in flow. > Also, whereas I prefer to illustrate 'how it works', I perceive that you > are used to learning 'rules' and only thereafter their application (the > teaching-practice under which most of us learned) - so, another reason > for mixing-things-up, to suit yourself (hopefully). Well observed. (I suppose it is a habit of mine to try to infer the axioms of things.) [...] > On 06/08/2021 05.35, Jack Brandom wrote: >> The FAQ at >> >> https://docs.python.org/3/faq/programming.html#what-s-a-negative-index >> >> makes me think that I can always replace negative indices with positive >> ones --- even in slices, although the FAQ seems not to say anything >> about slices. > > Yes, it can be done. I thought your own post confirmed it cannot. I'll point it out below. >> With slices, it doesn't seem to always work. For instance, I can >> reverse a "Jack" this way: >> >>>>> s = "Jack Brandom" >>>>> s[3 : -13 : -1] >> 'kcaJ' >> >> I have no idea how to replace that -13 with a positive index. Is it >> possible at all? > > Yes it is - but read on, gentle reader... > > If we envisage a string: > - a positive index enables the identification of characters, from > left-to-right > - a negative index 'counts' from right-to-left, ie it takes the > right-most elements/characters. > > The length of a string (sequence) is defined as len( str ). Accordingly, > there is a formula which can 'translate' the length and either statement > of the index's relative-location, to the other. To quote one of the > web.refs (offered below) "If i or j is negative, the index is relative > to the end of sequence s: len(s) + i or len(s) + j is substituted. But > note that -0 is still 0." > > Clear as mud? Please continue... > > >> But this example gives me the idea that perhaps each slice is equivalent >> to a certain loop (which I could write in a procedure). So I'm looking >> for these procedures. If I can have the procedures in mind, I think I >> will be able to undersand slices without getting surprised. >> >> Do you have these procedures from the top of your mind? While I haven't >> given up yet, I am not getting too close. Thank you! > > > Us Silver-Surfers have to stick-together. So, let's try closing the gap. > > Rather than attempting to re-build Python, perhaps some experimenting > with sequences, indexing, and slicing is what is required? I can see > writing a simulation routine as a perfectly-valid (proof of) > learning-approach - and one we often applied 'back then'. However, is it > the 'best' approach? (Only you can judge!) I like extreme clarity and certainty. While my approach did not give me too much certainty, at least I got a conjecture --- so I posted my hypothesis here to give everyone a chance to look and spot: ``oh, that's not gonna work''. Simulating in software is a great way to precisely describe how something works, so I did it. [...] > Alternately, (with apologies for 'cheating') this may be some help: That's great. >>>> print( " Pos Ltr Neg" ) >>>> print( " ndx ndx" ) >>>> for positive_index, > character, > negative_index in zip( range( 12 ), > name, > range( -12, 0 ) > ): > ... print( f"{ positive_index:4} { character } { negative_index:4}" ) > > Pos Ltr Neg > ndx ndx > 0 J -12 > 1 a -11 > 2 c -10 > 3 k -9 > 4 -8 > 5 B -7 > 6 r -6 > 7 a -5 > 8 n -4 > 9 d -3 > 10 o -2 > 11 m -1 So if we begin at, say, -2 and work backwards to the beginning of the string so as to include the "J", the index must be -13 --- there is no positive index that could take the place of -13. (And that's because --- I eventually realized --- there is no positive number to the left of zero. You, of course, notice the same. So why are you saying it's possible to substitute negative indices with positive?) [...] > Another reason why folk have difficulty with using an index or offset is > the subtle difference between "cardinal" and "ordinal" numbers. Cardinal > numbers are for counting, eg the number of letters in the name. Whereas, > ordinal numbers refer to a position, eg first, second, third... (there > are also "nominal numbers" which are simply labels, eg Channel 3 TV - > but we're not concerned with them). There is an implicit problem in that > Python uses zero-based indexing, whereas spoken language starts with a > word like "first" or "1st" which looks and sounds more like "one" than > "zero". Despite it being a junior-school 'math' topic, it is easy to > fail to recognise which of the two types of number is in-use. The len( > sequence ) provides a cardinal number. An index is an ordinal number. That's well-observed. But, as you say, "first" takes us to the number 1. It is not very easy to equate "first" with zero. So I might as well just forget about the distinction between cardinal and ordinal in Python indexing. > Using the "rules" (above) and transforming around len( "Jack" ), one > arrives at suitable 'translation' formulae/formulas: > > negative-index = -1 * ( len( sequence ) - positive-index ) > positive-index = len( sequence ) + negative-index That's nice. I didn't write them in this form and I suppose yours is superior. > The above rules describing an index do not apply to a slice's "start", > "stop", or "step" values! The documentation expresses: > > proper_slice ::= [lower_bound] ":" [upper_bound] [ ":" [stride] ] > lower_bound ::= expression > upper_bound ::= expression > stride ::= expression > > Elsewhere in the docs the rules are described using to i, j, and k. NB > in this context "k" is not the "stride"! Where are these production rules coming from? They're not at https://docs.python.org/3/reference/grammar.html The word ``stride'' doesn't appear in this grammar. [...] > Lesson: > Whereas some like to talk of ( start:stop:step ), it might be more > helpful to verbalise the relationships as "starting at:" and "stopping > before"! That's a nice vocabulary for the context. Thanks. [...] > Many people consider the "stride"/step to indicate a sub-selection of > elements from within the slice's defined extent. However, it may be more > helpful to consider the r?le of the stride as defining the 'direction' > in which elements will be selected (per 'reverse') - and thereafter its > 'step effect'. I agree. And also I stuck with thinking of slices as the procedures I wrote, so I will always think of them as loops. > Remembering the rules governing indexes/indices, be advised that these > do not apply to either the lower_bound or the upper_bound of a slice. > For example: > >>>> name[ +100 ] > Traceback (most recent call last): > File "", line 1, in > IndexError: string index out of range > > and: > >>>> name[ -100 ] > Traceback (most recent call last): > File "", line 1, in > IndexError: string index out of range > > yet: > >>>> name[ -100:+100 ] > 'Jack Brandom' > > Just as a "lower_bound" of 0 or None is taken to mean the first item in > the sequence, so any ludicrous value is also 'translated'. > > Similarly, despite knowing the length (of the example-data) is 12, a > slice's upper-bound that evaluates to a larger number will be 'rounded > down'. Nice. That's a case where my procedures (simulating slices) fail. Thanks! I'll refine them. [...] > The tricks differ if the 'target' is the family-name: > >>>> name[ 5: ] > 'Brandom' >>>> name[ -7: ] > 'Brandom' > > but to demonstrate with some non-default "bounds", (if you'll permit the > (weak-)humor - and with no insult intended to your good name) we could > describe distaste for a popular breakfast cereal (All Bran?): > >>>> name[ 1:9 ] > 'ack Bran' >>>> name[ -11:-3 ] > 'ack Bran' Lol. It's not even my name. I think maybe we should all use a different name at every post. Or perhaps a different name at every thread. The USENET is a place where poster names don't matter at all. It's only the content that matters. (``USENET is a strange place.'' -- Dennis Ritchie.) [...] > To round things out, here's some 'theory':- > > Contrary to practice, the Python Reference Manual (6.3.3 Slicings) says: > <<< > The formal syntax makes no special provision for negative indices in > sequences; however, built-in sequences all provide a __getitem__() > method that interprets negative indices by adding the length of the > sequence to the index (so that x[-1] selects the last item of x). The > resulting value must be a nonnegative integer less than the number of > items in the sequence, and the subscription selects the item whose index > is that value (counting from zero). Since the support for negative > indices and slicing occurs in the object?s __getitem__() method, > subclasses overriding this method will need to explicitly add that support. That's interesting. Thanks for the reference. It is precisely this kind of thing I was looking for. [...] > Finally, it is not forgotten that you want to code a loop which > simulates a slice with negative attributes. (although it is hoped that > after the above explanations (and further reading) such has become > unnecessary as a learning-exercise!) Has it become unnecessary? For using Python, sure. But as you noticed --- I like to see the rules and be able to write them myself. So it is necessary for certain types. :-) > Please recall that whilst a slice-object will not, a range-object will > work with a for-loop. So: > >>>> rng = range( 4, 0, -1 ) >>>> list( rng ) > [4, 3, 2, 1] >>>> for index in rng: > ... print( name[ index ], end=" " ) > ... > k c a >>> > > Oops! This looks familiar, so apply the same 'solution': > >>>> rng = range( 4, -1, -1 ) >>>> list( rng ) > [4, 3, 2, 1, 0] >>>> for index in rng: > ... print( name[ index ], end=" " ) > ... > k c a J > > The 'bottom line' is that such simulation code will become torturous > simply because indexes/indices follow different rules to slices! > > > Should you wish to persist, then may I suggest modifying mySlice(it, > beg, end, step = 1) to: > > def my_slice( sequence, lower_bound, upper_bound, stride=1 ): I will. Thanks for the advice. > and first splitting the implementation's decision-tree into two paths, > according to whether the stride is positive or negative, before getting > into 'the nitty-gritty'. That I had already done. > Perversely (if not, foolishly) I have indulged (and can't recommend > it!). Nevertheless, if you are determined, I will be happy to forward > some test conditions, upon request (caveat emptor!)... Yes, send me your tests! (``Caveat emptor'' noted.) (I had included all tests that appeared in this thread, but had missed, for example, "Jack Brandom"[-100 : 100]. Didn't occur to me this wouldn't blow an exception.) > Web.Refs/Further reading: > https://docs.python.org/3/tutorial/introduction.html > https://docs.python.org/3/reference/expressions.html#primaries > https://docs.python.org/3/library/functions.html > https://docs.python.org/3/tutorial/controlflow.html > https://docs.python.org/3/library/stdtypes.html#typesseq > https://docs.python.org/3/library/stdtypes.html#ranges > https://docs.python.org/3/reference/simple_stmts.html > https://docs.python.org/3/glossary.html > https://web.archive.org/web/20190321101606/https://plus.google.com/115212051037621986145/posts/YTUxbXYZyfi > https://docs.python.org/3/reference/datamodel.html Thank you so much. From rosuav at gmail.com Wed Aug 11 16:15:28 2021 From: rosuav at gmail.com (Chris Angelico) Date: Thu, 12 Aug 2021 06:15:28 +1000 Subject: some problems for an introductory python test In-Reply-To: <868s18b1p7.fsf@jevedi.com> References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86lf599zse.fsf@jevedi.xotimo> <868s18b1p7.fsf@jevedi.com> Message-ID: On Thu, Aug 12, 2021 at 5:00 AM Hope Rouselle wrote: > > Chris Angelico writes: > > > On Wed, Aug 11, 2021 at 4:18 AM Hope Rouselle wrote: > >> > >> Chris Angelico writes: > >> > >> [...] > >> > >> >> not disagreeing... and yeah I could have thought deeper about the > >> >> answer, but I still think "notthing has been OOP" -> "yes it has, they > >> >> just didn't realize it" was worth mentioning > >> > > >> > Oh yes, absolutely agree. > >> > >> At the same time, inside the machine nothing is OOP --- so all the OOP > >> is no OOP at all and they just didn't realize it? This seems to show > >> that OOP is about perspective. An essential thing for OOP is the > >> keeping of states. Closures can keep state, so having procedures as > >> first-class values allows us to say we are doing OOP too. (Arguments of > >> procedures are messages and function application is message passing, > >> with closures keeping a state --- and all the rest of OOP can be > >> implemented with enough such functional technology.) In summary, OOP > >> should not be defined as some special syntax, otherwise there is no OOP > >> in ``2 + 2''. > >> > >> Having said that, I totally agree with all the nitpicking. > > > > Object orientation is a particular abstraction concept. It's not a > > feature of the machine, it's a feature of the language that you write > > your source code in. I've done OOP using IDL and CORBA, writing my > > code in C and able to subclass someone else's code that might have > > been written in some other language. [1] Central tenets of OOP > > (polymorphism, inheritance, etc) can be implemented at a lower level > > using whatever makes sense, but *at the level that you're writing*, > > they exist, and are useful. > > > > Data types, variables, control flow, these are all abstractions. But > > they're such useful abstractions that we prefer to think that way in > > our code. So, *to us*, those are features of our code. To the > > computer, of course, they're just text that gets processed into > > actually-executable code, but that's not a problem. > > Total agreement. > > > So I would say that (in Python) there IS object orientation in "2 + > > 2", and even in the Python C API, there is object orientation, despite > > C not normally being considered an object-oriented language. > > But would you say that 2 + 2 is also an illustration of object > orientation in any other language too? In some languages it is; in others, it's not. For instance, REXX doesn't have polymorphism. You can add two numbers together using x+y, or you can concatenate two strings with x||y. There's no concept of doing the same operation (spelled the same way) on different data types. (Partly that's because REXX doesn't actually *have* data types, but it does a pretty good job of simulating strings, bignums, floats, arrays, mappings, etc.) But in many modern programming languages, yes, it would be a demonstration of some of the object orientation features. > Regarding C, I have many times said that myself. If I wrote assembly, > I'm sure I would do my best to create things like procedures --- a label > and some bureaucracy to get arguments in and a return value out. Oh absolutely. But you'd also have the option to shortcut things if you wanted to. For better or for worse. > > [1] And boy oh boy was that good fun. The OS/2 Presentation Manager > > had a wealth of power available. Good times, sad that's history now. > > I know OS/2 only by name. I never had the pleasure of using it. In > fact, I don't even know how it looks. I must be a little younger than > you are. But not too younger because I kinda remember its name. Was it > a system that might have thought of competing against Microsoft Windows? > :-) That's what my memory tells me about it. History lesson! Once upon a time, IBM and Microsoft looked at what Intel was producing, and went, hey, we need to design an operating system that can take advantage of the fancy features of this 80286 thing. So they collaborate on this plan to make a 16-bit protected mode OS. Unfortunately, things didn't work out too well, partly because this was when Microsoft was at its most monopolistic, and they ended up parting company. IBM continued to make OS/2, but Microsoft took their part of the code and made Windows NT out of it. (Aside: Windows NT's 16-bit applications and OS/2's 16-bit applications were actually identical and compatible. Unfortunately, Win32 introduced a very new API, so as soon as everyone moved to 32-bit everything, the schism became problematic. But it was actually possible to package up a single .EXE file with a 16-bit MS-DOS loader, a Win32 loader, and an OS/2 32-bit loader, all happily coexisting. PKZIP, the original definition of the zip file format, did exactly that, or at least had two out of the three (I don't quite remember if it went the whole way), making it extremely convenient to zip and unzip files on different computers.) In the latter half of the 1990s, Windows came in three broad flavours: the 16-bit Windows 3.x line, which ran purely on top of DOS; the 32-bit Windows 95 line, which was the "home" OS and had to be heavily compatible with Windows 3, but still doing more things; and the Windows NT line, which was aimed at businesses. OS/2 was a viable option for businesses, but almost nobody took it seriously as a home OS. And Microsoft was using its marketing machine to push Windows fairly hard, so most people went that way. OS/2 had all kinds of amazing features (for its time). The default file system, HPFS ("High Performance File System"... IBM was good at many things, but imaginative naming wasn't one of them), did a spectacular job of maintaining reliability and performance on the ever-growing hard disks of the time. Yes, it coped remarkably well, even on *gigantic* drives that could carry, ooh, an entire gigabyte of data! I'm not kidding! We even had a drive that had TWO gigabytes of space, and HPFS managed it beautifully! Plus, it had this fancy concept of "extended attributes"; on older systems (like MS-DOS's "FAT" family), a file might be Read-Only, Hidden, a System file, or needing to be Archived, and that was it - but on HPFS, you could attach arbitrary data like "File type: DeScribe Word Processor" or "Double click action: Run CASMake.cmd". This allowed the GUI to store all kinds of information *on the file itself* instead of needing hidden files (or, in Windows' case, the registry) to track that kind of thing. The default command interpreter and shell on OS/2 was fairly primitive by today's standards, and was highly compatible with the MS-DOS one, but it also had the ability to run REXX scripts. REXX was *way* ahead of its time. It's a shell language but remarkably well suited to building GUIs and other tools (seriously, can you imagine designing a GUI entirely in a bash script??). It had features that we'd consider fairly normal or even primitive by Python's standards, but back then, Python was extremely new and didn't really have very much mindshare. REXX offered arbitrary-precision arithmetic, good databasing support, a solid C API that made it easy to extend, integrations with a variety of other systems... this was good stuff for its day. (REXX is still around, but these days, I'd rather use Python.) I mentioned the Presentation Manager, because it was one of the best parts of running OS/2. The kernel was decent, but it was the graphical shell that was the real pleasure to work with. Probably the most notable feature, by today's standards, was that it had a single input queue. If you press a series of keys, they'd go into a global queue, and the application that has focus would get the first one. When that key has been handled, the application that has focus would get the next key from the queue. This means that, if the response to a keystroke is to change focus, then *even in a slow and lagged out system*, subsequent keys WOULD be sent to the new target window. That was AWESOME, and I really miss it. Except that I also don't. Because if a single application is having issues, now your entire keyboard and mouse is locked up... which kinda slightly sucks. Good luck resolving that problem. (We had some neat tools like WatchCat that could get around the single input queue via interrupt signals, and regain control. But it was still problematic.) So, yeah. It was spectacular in its day.... but it kinda got left behind as the world moved on. These days, instead of running REXX code on OS/2 in a system that uses eight-bit text for most things, I use Python on Linux and full Unicode. But OS/2 was an important part of history, both my own personal journey, and the history of the world of PCs. ChrisA From rob.cliffe at btinternet.com Wed Aug 11 17:03:21 2021 From: rob.cliffe at btinternet.com (Rob Cliffe) Date: Wed, 11 Aug 2021 22:03:21 +0100 Subject: some problems for an introductory python test In-Reply-To: <6382edc7-ac3f-7b7b-a183-c109f9fb5b8b@mrabarnett.plus.com> References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86sfzha1ac.fsf@jevedi.xotimo> <861r71c7nw.fsf@jevedi.com> <30ad3e32-c7f5-e255-4c18-0147a56c3346@gmail.com> <6382edc7-ac3f-7b7b-a183-c109f9fb5b8b@mrabarnett.plus.com> Message-ID: On 11/08/2021 19:10, MRAB wrote: > On 2021-08-11 18:10, Wolfram Hinderer via Python-list wrote: >> >> >> Am 11.08.2021 um 05:22 schrieb Terry Reedy: >>> Python is a little looser about whitespace than one might expect >>> from reading 'normal' code when the result is unambiguous in that it >>> cannot really mean anything other than what it does.? Two other >>> examples: >>> >>> >>> if3: print('yes!') >>> yes! >>> >>> [0]? [0] >>> 0 >> >> Not sure what you mean here - is it a joke? The first looks like an if >> statement, but isn't. The missing space *does* make a difference. (Try >> "if0" instead.) >> > I see what you mean. It's a type annotation: > > ??? var: type > > where the "type" is a print statement! > >> The second is normal indexing, which allows white space. I wouldn't >> consider that surprising, but maybe I should? (Honest question, I really >> don't know.) >> I looked at the if3 example, and I was gobsmacked.? I momentarily assumed that "if3" was parsed as "if 3", although that clearly makes no sense ("if3" is a valid identifier). Then I saw the "if0" example and I was even more gobsmacked, because it showed that my assumption was wrong. I've never used type annotations, I've never planned to used them. And now that all is revealed, I'm afraid that my reaction is: I'm even more inclined never to use them, because these examples are (to me) so confusing. Rob Cliffe From avigross at verizon.net Wed Aug 11 17:31:31 2021 From: avigross at verizon.net (Avi Gross) Date: Wed, 11 Aug 2021 17:31:31 -0400 Subject: some problems for an introductory python test In-Reply-To: References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86lf599zse.fsf@jevedi.xotimo> <868s18b1p7.fsf@jevedi.com> Message-ID: <00ca01d78ef8$40fcec70$c2f6c550$@verizon.net> This conversation has, of course, veered away from the original question so I am starting afresh. My memory of the original question is about how one sets up a test for material covered in class or associated materials for what sounds like a beginner class. I am not sure whether this would be the place for anyone to ask such a question, especially as we have no real idea what was taught and expected. Python is too rich a language and can be taught all kinds of ways including many that largely ignore object-orientedness or other ways that professionals use and appreciate. There are lots of others who have taught such classes and plenty of books. One can look to see what kinds of questions they use, and, where allowed, borrow some, suitably adjusted. Any textbooks actually used for a course may be an excellent place to start. When I have taught, I like to do things incrementally. Tests are made up based on what is talked about and stressed, perhaps with harder questions asking for some innovation. So you may end up teaching how to do some things without loops such as the example where you largely repeat some code in-line five times. You might show how to do the same thing using dreaded GOTO-statements in the OLD days but rarely now. Nowadays you might introduce while loops or their repeat/do/for variants. In Python, you may well introduce abbreviated variants such as list comprehensions. So if testing the above, it is fair to specify in a question what NOT to use. You can ask for no use of loops, or you can specify you want them to use nothing but methods X or Y and so on. And since there are so many modules out there, you might specify that no importing is allowed as that defeats the purpose. I mean, if the purpose is to teach them how to logically write a program that implements an algorithm as compared to just calling a function already made. As noted, some very decent projects are simply asking the student to create something others have already done and one way to test how well they did it is to compare the output of their work with a debugged solution. Real programmers may at some point shift to using all kinds of constructs that help them write lots of code faster and with fewer errors but beginner students need something not very low level (like assembler?) but also not very high level, I would think. But debates about object oriented are fine for us philosophers but not really of much use for the question I thought was asked. From rosuav at gmail.com Wed Aug 11 17:36:09 2021 From: rosuav at gmail.com (Chris Angelico) Date: Thu, 12 Aug 2021 07:36:09 +1000 Subject: some problems for an introductory python test In-Reply-To: References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86sfzha1ac.fsf@jevedi.xotimo> <861r71c7nw.fsf@jevedi.com> <30ad3e32-c7f5-e255-4c18-0147a56c3346@gmail.com> <6382edc7-ac3f-7b7b-a183-c109f9fb5b8b@mrabarnett.plus.com> Message-ID: On Thu, Aug 12, 2021 at 7:25 AM Rob Cliffe via Python-list wrote: > > On 11/08/2021 19:10, MRAB wrote: > > On 2021-08-11 18:10, Wolfram Hinderer via Python-list wrote: > >> > >> > >> Am 11.08.2021 um 05:22 schrieb Terry Reedy: > >>> Python is a little looser about whitespace than one might expect > >>> from reading 'normal' code when the result is unambiguous in that it > >>> cannot really mean anything other than what it does. Two other > >>> examples: > >>> > >>> >>> if3: print('yes!') > >>> yes! > >>> >>> [0] [0] > >>> 0 > >> > >> Not sure what you mean here - is it a joke? The first looks like an if > >> statement, but isn't. The missing space *does* make a difference. (Try > >> "if0" instead.) > >> > > I see what you mean. It's a type annotation: > > > > var: type > > > > where the "type" is a print statement! > > > >> The second is normal indexing, which allows white space. I wouldn't > >> consider that surprising, but maybe I should? (Honest question, I really > >> don't know.) > >> > I looked at the if3 example, and I was gobsmacked. I momentarily > assumed that "if3" was parsed as "if 3", although that clearly makes no > sense ("if3" is a valid identifier). > Then I saw the "if0" example and I was even more gobsmacked, because it > showed that my assumption was wrong. > I've never used type annotations, I've never planned to used them. And > now that all is revealed, I'm afraid that my reaction is: I'm even more > inclined never to use them, because these examples are (to me) so confusing. Don't judge a feature based on its weirdest example. Based on this example, you should avoid ever using the len() built-in function: >>> def show_count(n, word): ... return "{{}} {{:{0}.{0}}}".format(len(word)-(n==1)).format(n, word) ... >>> show_count(0, "things") '0 things' >>> show_count(1, "things") '1 thing' >>> show_count(5, "things") '5 things' >>> show_count(2, "widgets") '2 widgets' >>> show_count(1, "widgets") '1 widget' Any syntax can be abused. And the same thing would happen in any other context. The only difference is that, in a declaration like "if3: print()", the name if3 doesn't have to have been assigned already, avoiding this problem: >>> { ... if3: print("Hello") ... } Traceback (most recent call last): File "", line 2, in NameError: name 'if3' is not defined ChrisA From wlfraed at ix.netcom.com Wed Aug 11 18:32:03 2021 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Wed, 11 Aug 2021 18:32:03 -0400 Subject: on slices, negative indices, which are the equivalent procedures? References: <86sfznhk1f.fsf@example.com> <86wnos9ge8.fsf@jevedi.com> Message-ID: <4vi8hg1tfcd2vsrchgpnbpf9a9l7acf7rl@4ax.com> On Wed, 11 Aug 2021 11:59:11 -0300, Jack Brandom declaimed the following: > >Where are these production rules coming from? They're not at > > https://docs.python.org/3/reference/grammar.html > >The word ``stride'' doesn't appear in this grammar. > Possibly from older versions of the grammar, before simplification to just . Originally, the "stride" term was added in response to requests from the numerical library developers (NumPy seems to be the survivor of that cluster). At the time, it wasn't envisioned to be usable with regular Python objects. https://en.wikipedia.org/wiki/Array_slicing#1991:_Python """ The stride syntax (nums[1:5:2]) was introduced in the second half of the 1990s, as a result of requests put forward by scientific users in the Python "matrix-SIG" (special interest group). """ As for the grammar... Would you prefer that from 2.7? trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME subscriptlist: subscript (',' subscript)* [','] subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] sliceop: ':' [test] test: or_test ['if' or_test 'else' test] | lambdef or_test: and_test ('or' and_test)* and_test: not_test ('and' not_test)* not_test: 'not' not_test | comparison -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From wlfraed at ix.netcom.com Wed Aug 11 18:51:14 2021 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Wed, 11 Aug 2021 18:51:14 -0400 Subject: some problems for an introductory python test References: <86lf599zse.fsf@jevedi.xotimo> <868s18b1p7.fsf@jevedi.com> Message-ID: On Thu, 12 Aug 2021 06:15:28 +1000, Chris Angelico declaimed the following: >The default command interpreter and shell on OS/2 was fairly primitive >by today's standards, and was highly compatible with the MS-DOS one, >but it also had the ability to run REXX scripts. REXX was *way* ahead >of its time. It's a shell language but remarkably well suited to >building GUIs and other tools (seriously, can you imagine designing a >GUI entirely in a bash script??). It had features that we'd consider >fairly normal or even primitive by Python's standards, but back then, >Python was extremely new and didn't really have very much mindshare. >REXX offered arbitrary-precision arithmetic, good databasing support, >a solid C API that made it easy to extend, integrations with a variety >of other systems... this was good stuff for its day. (REXX is still >around, but these days, I'd rather use Python.) > I was spoiled by the Amiga variant of REXX. Most current implementations (well, Regina is the only one I've looked at) can just pass command to the default shell. The Amiga version took advantage of Intuition Message Ports (OS supported IPC). That allowed it to "address " any application that defined an ARexx port, allowing ARexx to be used as a scripting language for that application (and with multiple applications, one could easily fetch data from app1 and feed it to app2). ARexx did not, to my memory, implement arbitrary precision math. Any statement in a REXX script that was not parsable as REXX would be passed on the currently "addressed" command host. Granted, the fact that the Amiga used a shared common address space for all running applications made IPC quite easy -- one looked up the application message port, then added a small packet to the linked list associated with the port. That small packet basically held the address of the message port for returning data, and the address of the data being passed. The closet thing I've seen to that capability on systems with process-isolated virtual memory is (Open)VMS "mailbox" structures. The difference being that the entire data had to be written (QIO) to the mailbox, and the receiver had to read (another QIO call) the message -- this allowed the address space to change. I've not seen anything equivalent in my light perusal of the Win32 API (the various guide books aren't layed out in any way to be a reference), and Linux seems to use UNIX sockets for IPC... No way to search for a connection point by name... But I've harangued long enough. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From wlfraed at ix.netcom.com Wed Aug 11 19:19:44 2021 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Wed, 11 Aug 2021 19:19:44 -0400 Subject: some problems for an introductory python test References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86sfzha1ac.fsf@jevedi.xotimo> <86czqkb1z9.fsf@jevedi.com> Message-ID: On Wed, 11 Aug 2021 09:27:38 -0300, Hope Rouselle declaimed the following: > >I wouldn't. This is all Python-stuff. The course chooses a language >like Python, but it is not trying to teach Python --- it is trying to >teach computer programming, that is, strategies in high-precision. > Then I would posit you are teaching the wrong level... What you describe is what would be found a "data structures" and/or "algorithms" course -- which is a second year, if not third year course in my (ancient) history. Such a course presumes one already knows at least on programming language well enough that they can take description of an algorithm (or even more detailed, pseudo-code) and translate it into the language they know. This means the students /must/ know basic if/then/else, iterative looping (which may, at common core, mean coding with a numerical index, rather than pulling objects themselves out of the indexable structure -- since not all languages support object iteration), conditional looping (including how to turn a "repeat/until" into the equivalent "while" (I was tempted to say "while/wend" but that is specific to languages that need block terminators). Slicing with a stride isn't really useful to most algorithm development -- it's more of trick in normal Python. So... The first thing I would drop is the RESTRICTION to only use what you've covered in prior sessions... Let the students read the language reference manual, peruse the library reference manual, and allow them to use whatever "advanced" techniques they are able to understand on their own. Granted you may have to restrict some features if discussing a "common" data structure (queue, stack, maybe even advanced list manipulation -- allow pop() and del, as those are how one would implement queue and stack). Same for sorting -- if covering bubble, insertion, heap, and (horrors) multipass sort/merge using working files, obviously the Python sort()/sorted() are off-limits. For my Algorithm/Data Structure course (circa 1978), the instructor allowed us to use any language /he/ could understand (so no SNOBOL). At the time I'd gone through intro/advanced FORTRAN-4, intro/advanced COBOL, Sigma Assembly, UCSD Pascal (not on the campus main computer, just a pair of LSI-11s), and BASIC. The assignment was a "Hashed Head, Multiply-Linked List". I chose to do that assignment using BASIC! In nearly 45 years, I've only seen ONE real-world implementation of the HHMLL -- The file system used by the Commodore Amiga. (Hash the first component of the path/name, that maps to one of 64 entries in the root directory block; each entry points the start of a linked list, follow the list until you reach the block with the component name; if it is a directory block, hash the next component and repeat; if it is a file block, the "entries" point to data blocks instead of lists) -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From rosuav at gmail.com Wed Aug 11 19:33:48 2021 From: rosuav at gmail.com (Chris Angelico) Date: Thu, 12 Aug 2021 09:33:48 +1000 Subject: some problems for an introductory python test In-Reply-To: References: <86lf599zse.fsf@jevedi.xotimo> <868s18b1p7.fsf@jevedi.com> Message-ID: On Thu, Aug 12, 2021 at 9:23 AM Dennis Lee Bieber wrote: > > On Thu, 12 Aug 2021 06:15:28 +1000, Chris Angelico > declaimed the following: > > > >The default command interpreter and shell on OS/2 was fairly primitive > >by today's standards, and was highly compatible with the MS-DOS one, > >but it also had the ability to run REXX scripts. REXX was *way* ahead > >of its time. It's a shell language but remarkably well suited to > >building GUIs and other tools (seriously, can you imagine designing a > >GUI entirely in a bash script??). It had features that we'd consider > >fairly normal or even primitive by Python's standards, but back then, > >Python was extremely new and didn't really have very much mindshare. > >REXX offered arbitrary-precision arithmetic, good databasing support, > >a solid C API that made it easy to extend, integrations with a variety > >of other systems... this was good stuff for its day. (REXX is still > >around, but these days, I'd rather use Python.) > > > I was spoiled by the Amiga variant of REXX. Most current > implementations (well, Regina is the only one I've looked at) can just pass > command to the default shell. The Amiga version took advantage of Intuition > Message Ports (OS supported IPC). That allowed it to "address > " any application that defined an ARexx port, allowing ARexx > to be used as a scripting language for that application (and with multiple > applications, one could easily fetch data from app1 and feed it to app2). > ARexx did not, to my memory, implement arbitrary precision math. The same functionality was available in OS/2, but not heavily used. You could 'address cmd commandname' to force something to be interpreted as a shell command, but that was about it. However, I built a MUD that used REXX as its scripting language, and the default destination was sending text back to the person who sent the command; and you could, of course, still 'address cmd' to run a shell command. > I've not seen anything equivalent in my light perusal of the Win32 API > (the various guide books aren't layed out in any way to be a reference), > and Linux seems to use UNIX sockets for IPC... No way to search for a > connection point by name... > Win32 doesn't really have it. Unix sockets are kinda there but you identify something by a path to the socket, not the name of the application. But I think dbus is probably the closest to what you're thinking of. ChrisA From PythonList at DancesWithMice.info Wed Aug 11 20:40:32 2021 From: PythonList at DancesWithMice.info (dn) Date: Thu, 12 Aug 2021 12:40:32 +1200 Subject: on slices, negative indices, which are the equivalent procedures? In-Reply-To: <86wnos9ge8.fsf@jevedi.com> References: <86sfznhk1f.fsf@example.com> <86wnos9ge8.fsf@jevedi.com> Message-ID: On 12/08/2021 02.59, Jack Brandom wrote: > dn writes: > ... >> Also, whereas I prefer to illustrate 'how it works', I perceive that you >> are used to learning 'rules' and only thereafter their application (the >> teaching-practice under which most of us learned) - so, another reason >> for mixing-things-up, to suit yourself (hopefully). > > Well observed. (I suppose it is a habit of mine to try to infer the > axioms of things.) After a career involving various forms of vocational training and tertiary education, I've met many different folk, (ultimately) each with his/her own approach. Undoubtedly, the best way to answer someone's question is to understand why they are asking in the first place. Learning a programming language requires the alignment of one's own "mental model" with that of the language's rules and idioms. Thus, understanding your mental model enables a third-party to understand where correction may be necessary or omission exists. [can you tell that my colleagues and I were having just this discussion this morning?] Having spent the last few years working with a series of MOOCs (usual disclaimers: edX platform, not Python topics) I've noticed that when we first started, our trainees were almost-exclusively post-grads, ie had a 'learning habit', curiosity, a set of expectations, and (most of the time) some computing background. As time has gone by, these characteristics have all changed, eg the expectations have broadened and may be more 'interest' than 'professional, and we cannot expect that everyone has met software development previously... That's also a characteristic of the Python language: that as it has become more popular, the 'new entrants' are very different people, and the 'new features' and (newly) added libraries have become more diverse (in application)! NB "axioms" is basically "mental model". >> On 06/08/2021 05.35, Jack Brandom wrote: >>> The FAQ at >>> >>> https://docs.python.org/3/faq/programming.html#what-s-a-negative-index >>> >>> makes me think that I can always replace negative indices with positive >>> ones --- even in slices, although the FAQ seems not to say anything >>> about slices. >> >> Yes, it can be done. > > I thought your own post confirmed it cannot. I'll point it out below. Yes, it can! (key means to starting a 'religious war'). (not starting a 'war', or even meaning to be unkind, I'm embarking on a Socratic approach rather than giving you an immediate answer - you can handle it/beat me up later...) Just maybe you are guilty of (only) 'thinking inside the box'? Have you come-across the 'connect nine dots with four lines' brain-teaser? https://lateralaction.com/articles/thinking-outside-the-box/ >>> With slices, it doesn't seem to always work. For instance, I can >>> reverse a "Jack" this way: >>> >>>>>> s = "Jack Brandom" >>>>>> s[3 : -13 : -1] >>> 'kcaJ' If this were a fight (between us), there is me 'hitting' you with the answer. However, the 'fight' is waiting for 'the penny to drop' in your mind. So, please continue:- As warned, here's where the misapprehensions begin:- >>> But this example gives me the idea that perhaps each slice is equivalent >>> to a certain loop (which I could write in a procedure). So I'm looking ... Then the old men begin waving their walking-sticks around (whilst others wish there was such a thing as a negative-walking-stick):- >> Us Silver-Surfers have to stick-together. So, let's try closing the gap. ... > I like extreme clarity and certainty. While my approach did not give me > too much certainty, at least I got a conjecture --- so I posted my > hypothesis here to give everyone a chance to look and spot: ``oh, that's > not gonna work''. Simulating in software is a great way to precisely > describe how something works, so I did it. Eminently reasonable. The 'problem' (and it lies at the very roots of instructional design) is that 'learning Python' involves BOTH width and depth, ie there's a lot to learn! 'Pop Psy' talks about a 'learning curve' and how steep it might be... After a while, one realises that it is not necessary to learn the full 'width' - after all, does that mean just 'Python', does it include the PSL (Python Standard Library), does it stop at PyPi, or where? Similarly, with depth - is it worth knowing all there is to know about slicing or might a study of comprehensions yield more 'fruit'? On this list, I've referred more than once to, "some 'dark corner of Python' in which I've never previously ventured". Python is described as having a relatively-shallow learning curve (cf Java, for example), which evidences/presumes a more breadth-first approach. Accordingly, how does one split-up 'learning Python' into manageable "chunks" - or in the words of software development, an MVP (Minimum Viable Product)? An answer to that may be to get 'a good handle on' positive indexing, and then 'move on'. Thus, characteristics such as zero-base, < len( sequence ), etc. Later, when either an advanced topic or a work-assignment demands, only then might we need to return to indexing to learn how negative-indexes facilitate access from 'right-to-left' (string imagery). Thus, in Python parlance: we re-factor our own knowledge-base and capabilities, in the same way that re-factoring code improves same! So, *providing* we realise and remember that positive indexes/indices are only a shallow-understanding, and when the need arises, return to augment that basic knowledge; such a learning-practice is (at least) 'good enough'. (cf my sarcastic term of "Stack Overflow-driven development", which all too often translates to zero-learning. Therein appears to lie 'survival', but 'blind-acceptance' rather than absorbed-knowledge, also risks a close encounter with 'danger' - "here be dragons"!) Accordingly, (on my side of the fence) a Python Apprentice needs to learn positive-indexing in order to be useful on his/her first day at work. (S)he becomes a Python Journeyman once negative-indexing has been learned (and applied). Onwards and upwards! Thus, does being able to program(me) replacement code for built-in facility, ie coding axioms, fall into the field of the Apprentice, the Journeyman, or the Master? Some like to talk of "learning styles" (again: PopPsy, thoroughly debunked, and without serious proof, despite its initial 'attraction'). The application of styles should be to topic, even sub-topic. It is *very* limiting when an individual assumes/determines that (s)he has a particular learning style, ie "I am a kinaesthetic/kinesthetic learning" meaning 'has to move or feel whatever is being learned', when it is followed by 'and this is the *only* way I can learn'. The person has immediately limited him-/her-self! I suggest that learning Python involves 'movement' in the sense that the best way to prove learning (as indeed you have said) is to write code - perhaps not because that might involve typing, head-scratching, throwing things 'out the window' in frustration, etc. However, the 'learning' likely involves reading and thinking (to form that 'mental model'). After that, it is the 'proof of learning' which involves 'movement'! (what a tenuous claim!) Thus, 'learning styles' are best adapted: what is the best style to use when learning (training) this particular 'chunk' of material? Can I express this is more than one manner (recall my disappointment at not being able to include schematic diagrams in a list-post). Accordingly, adaptability cf a rigid approach (despite phrases such as 'time-tested' because they, like 'my [only] style' are ultimately self-limiting)! Back to allusions with computer science, where we find an interesting conundrum when looking through a mass of inter-connected data (usually called a "network"). In which sequence do we process (learn) all of the individual items? Do we work our way 'across' and then 'down', or go all the way 'down' and then come back 'up' in order to work our way 'across'? eg Graph Traversals - Breadth First and Depth First (https://www.youtube.com/watch?v=bIA8HEEUxZI) You can likely see where I'm going with this: the less one has to learn in one "chunk", the easier the learning. Accordingly, something of a width-first approach. (yes, contrarily: "a little bit of knowledge is a dangerous thing") However, this depends to some degree upon one's ability to keep that in-mind when some new 'challenge' arises. Particularly that one not feel that re-visiting a topic, eg to pick-up negative-indexing, is 'going backwards', but recognise that it is adding "depth" to one's existing (wider) knowledge! Further reading: Perhaps your "satiable curtiosity" will tempt you to take a dip in the Limpopo River and contemplate the "six honest serving-men...What and Where and When And How and Why and Who" (Rudyard Kipling, but not India for a change. http://www.online-literature.com/kipling/165/) Also a book, if you'd like to leave syntax and semantics and delve into some related philosophy, "Insatiable Curiosity - Innovation in a Fragile Future" (https://mitpress.mit.edu/books/insatiable-curiosity) ... > So if we begin at, say, -2 and work backwards to the beginning of the > string so as to include the "J", the index must be -13 --- there is no > positive index that could take the place of -13. (And that's because > --- I eventually realized --- there is no positive number to the left of > zero. You, of course, notice the same. So why are you saying it's > possible to substitute negative indices with positive?) Because the statement (above) conflates two concepts: indexing and slicing! Please recall earlier warnings that the two exhibit fundamental differences! Also, remember our "fudging" that zero be treated as a positive-integer, when it is plainly not? There is also the concept that a slice with 'missing' values, ie which invokes the defaults, is also 'fudging' whether the None is a positive- or negative- integer (depending upon the 'direction' of the stride - or its default)! Hey, if we're going to 'cheat' like this, then let's go whole-hog. Sorry, wrong animal: "you might as well be hung for a sheep as for a lamb" - and not a snake in sight! If we talk about the "J", then an index is used to access that element of the sequence - forwards or backwards, as desired. So, an index of -12 becomes +0. Exactly as claimed. Exactly per docs. However, the task is "begin at, say, -2 and work backwards to the beginning of the string". This is a task for slicing not indexing! (if you haven't 'twigged' after the 'think outside the box' hint, above; then I'm teasing you. Forget 'war', and please read on...) >> Another reason why folk have difficulty with using an index or offset is >> the subtle difference between "cardinal" and "ordinal" numbers. Cardinal >> numbers are for counting, eg the number of letters in the name. Whereas, >> ordinal numbers refer to a position, eg first, second, third... (there >> are also "nominal numbers" which are simply labels, eg Channel 3 TV - >> but we're not concerned with them). There is an implicit problem in that >> Python uses zero-based indexing, whereas spoken language starts with a >> word like "first" or "1st" which looks and sounds more like "one" than >> "zero". Despite it being a junior-school 'math' topic, it is easy to >> fail to recognise which of the two types of number is in-use. The len( >> sequence ) provides a cardinal number. An index is an ordinal number. > > That's well-observed. But, as you say, "first" takes us to the number > 1. It is not very easy to equate "first" with zero. So I might as well > just forget about the distinction between cardinal and ordinal in Python > indexing. No! The difference is extremely important, even if you start talking (?babbling) about 'the zero-th entry'! Read on... >> Using the "rules" (above) and transforming around len( "Jack" ), one >> arrives at suitable 'translation' formulae/formulas: >> >> negative-index = -1 * ( len( sequence ) - positive-index ) >> positive-index = len( sequence ) + negative-index > > That's nice. I didn't write them in this form and I suppose yours is > superior. Superior is a lake - and not the one you're on. You're on "Huron". (apologies, a little Illinois humor - if you can call it that) >> The above rules describing an index do not apply to a slice's "start", >> "stop", or "step" values! The documentation expresses: >> >> proper_slice ::= [lower_bound] ":" [upper_bound] [ ":" [stride] ] >> lower_bound ::= expression >> upper_bound ::= expression >> stride ::= expression ... > Where are these production rules coming from? They're not at > https://docs.python.org/3/reference/grammar.html You'll find them, when you have time to catch-up with all the web.refs - that breadth-first/depth-first conundrum rises again! (- way before the "Full Grammar" (which is a summary of the entire doc), in https://docs.python.org/3/reference/expressions.html#primaries) > The word ``stride'' doesn't appear in this grammar. No but "slices" do! (this topic seems to have collected a confusing collection of nomenclature, to the point of obfuscation!) > [...] > >> Lesson: >> Whereas some like to talk of ( start:stop:step ), it might be more >> helpful to verbalise the relationships as "starting at:" and "stopping >> before"! > > That's a nice vocabulary for the context. Thanks. idiom > noun (don't tell any English-language linguists I said that!) > [...] >> Many people consider the "stride"/step to indicate a sub-selection of >> elements from within the slice's defined extent. However, it may be more >> helpful to consider the r?le of the stride as defining the 'direction' >> in which elements will be selected (per 'reverse') - and thereafter its >> 'step effect'. > > I agree. And also I stuck with thinking of slices as the procedures I > wrote, so I will always think of them as loops. Yes! (your thinking is climbing out of that "box"! - but am still concerned about 'coding the axiom' holding back your understanding) >> Remembering the rules governing indexes/indices, be advised that these >> do not apply to either the lower_bound or the upper_bound of a slice. ... >>>>> name[ -100:+100 ] >> 'Jack Brandom' Another hint. (OK, now he's just being cruel!) >> Just as a "lower_bound" of 0 or None is taken to mean the first item in >> the sequence, so any ludicrous value is also 'translated'. >> >> Similarly, despite knowing the length (of the example-data) is 12, a >> slice's upper-bound that evaluates to a larger number will be 'rounded >> down'. > > Nice. That's a case where my procedures (simulating slices) fail. > Thanks! I'll refine them. You see - it's actually 'right there', standing at the very edge of your reasoning! > [...] >> but to demonstrate with some non-default "bounds", (if you'll permit the >> (weak-)humor - and with no insult intended to your good name) we could >> describe distaste for a popular breakfast cereal (All Bran?): >> >>>>> name[ 1:9 ] >> 'ack Bran' >>>>> name[ -11:-3 ] >> 'ack Bran' > > Lol. It's not even my name. I think maybe we should all use a > different name at every post. Or perhaps a different name at every > thread. The USENET is a place where poster names don't matter at all. > It's only the content that matters. (``USENET is a strange place.'' -- > Dennis Ritchie.) Remote courses (like ours) are (justly) criticised for lacking the social interaction of a 'class room', particularly the inter-personal relationship between tutor and trainee. Nevertheless, it surprises me that it is quite possible to recognise people by their writing, the way they ask questions, etc. (it shouldn't (be a surprise), because Morse Code operators were able to identify each other purely by their "fist" - not even with the hint of the name/label which we can see on email, discussion boards, etc) Whereas lists are general - this response goes not only to you, but to anyone/everyone else who may be interested. Regardless of "lurkers" (people paying attention but not making their 'presence' known) I'd argue that it is better to be able to address a person as an individual. Accordingly, I prefer 'real names'. That said, I go by "dn" which appears two-faced. The rationale is that there seems to always be another "David" within hearing distance; and my family name, "Neil", is also used as a given-name, and also reasonably popular. A pathetic attempt at asserting my uniqueness - maybe... The other side of that is the use of illegal email addresses. These are a pain to server admins and list admins alike, as they generate bounce-back messages and failures to the log. This 'polluting traffic' is why email practice changed to never 'returning' spam messages, but only allowing them to become lost in cyber-space. Fine for spam, but irritating should one slightly mis-type a correct address (and thus not be aware of the communication-failure until 'it is too late'!). The related consideration may be allayed by the fact that (to-date) I have not experienced either this list's email address or my (slightly different) address over on the Python-Tutor list, being 'harvested' and used for spam. There's also an inherent irony in being prepared to ask others for help, but not being sufficiently 'honest' to use your own name and address. The net effect (punny hah, hah!) is to add traffic (to the community) in an attempt to reduce traffic (for yourself)... > [...] >> <<< >> The formal syntax makes no special provision for negative indices in >> sequences; however, built-in sequences all provide a __getitem__() >> method that interprets negative indices by adding the length of the >> sequence to the index (so that x[-1] selects the last item of x). The >> resulting value must be a nonnegative integer less than the number of >> items in the sequence, and the subscription selects the item whose index >> is that value (counting from zero). Since the support for negative >> indices and slicing occurs in the object?s __getitem__() method, >> subclasses overriding this method will need to explicitly add that support. > > That's interesting. Thanks for the reference. It is precisely this > kind of thing I was looking for. Utilising this is way 'up' in Python-Master country! > [...] >> Finally, it is not forgotten that you want to code a loop which >> simulates a slice with negative attributes. (although it is hoped that >> after the above explanations (and further reading) such has become >> unnecessary as a learning-exercise!) > > Has it become unnecessary? For using Python, sure. But as you noticed > --- I like to see the rules and be able to write them myself. So it is > necessary for certain types. :-) Accordingly, we shall continue... (whilst also keeping range and slice objects, and their differences, in-mind) >> Please recall that whilst a slice-object will not, a range-object will >> work with a for-loop. So: >> >>>>> rng = range( 4, 0, -1 ) >>>>> list( rng ) >> [4, 3, 2, 1] >>>>> for index in rng: >> ... print( name[ index ], end=" " ) >> ... >> k c a >>> >> >> Oops! This looks familiar, so apply the same 'solution': >> >>>>> rng = range( 4, -1, -1 ) >>>>> list( rng ) >> [4, 3, 2, 1, 0] >>>>> for index in rng: >> ... print( name[ index ], end=" " ) >> ... >> k c a J Here is the 'solution' to your unsatisfied question, but using 'positive indexing'! (with negative entries in the range, including the stride!) >> The 'bottom line' is that such simulation code will become torturous >> simply because indexes/indices follow different rules to slices! Did I say "torturous"? Should it have been "tortuous"? Why did I say it? Does either or both apply? Right, back to your question (finally!): <<< So if we begin at, say, -2 and work backwards to the beginning of the string so as to include the "J", the index must be -13 --- there is no positive index that could take the place of -13. (And that's because --- I eventually realized --- there is no positive number to the left of zero. You, of course, notice the same. So why are you saying it's possible to substitute negative indices with positive?) >>> The problem appears as: >>> name[ -10:-12:-1 ] 'ca' Treating this as an indexing-problem, we can go back to the 'chart': Pos Ltr Neg ndx ndx 0 J -12 1 a -11 2 c -10 3 k -9 ... and we can see that 'out by one' issue is (apparently) preventing us from getting out the "J". Now J has the index -12, and we've used that; but we refer to that the "stop-before" command and we want it included ("closed" not "open"). Oops! or arggggghhhhh! If we continue to treat it as an indexing-problem, what we'd like to do is use an index of -13 - but that ain't goin' to fly [Wilbur]: >>> name[ -13 ] Traceback (most recent call last): File "", line 1, in IndexError: string index out of range The issue stems from the warning that indexes follow one set of rules, and slices (which might be seen as presenting like multiple indexes/indices) march to the tune of a different drum! Thus, change gear and approach the matter as a slicing-problem! Now, we can go outside the box/off the top of the chart (reproduced above): >>> name[ -2:-13:-1 ] 'odnarB kcaJ' or we can take advantage of the idea that slices can be specified with missing components - in this case the upper-bound. Instead, asking for default-values to be substituted*: >>> name[ -2::-1 ] 'odnarB kcaJ' * either len( sequence ) or because this case involves a negative-stride: -len( sequence ) - 1 PS the ability to 'over-run'?'under-run' the negative index 'limit' in a slice was mentioned (but has been edited-out of the response): <<< The reverse direction requires a re-think of the lower-bound value we were using (above) and may necessitate a review of the schematics presented earlier, in conjunction with the closed-open convention: >>> name[ 4-1::-1 ] 'kcaJ' >>> and <<< What is rather handy, is that using a negative (unity) stride has the effect of reversing the string (sequence): >>> name[ ::-1 ] 'modnarB kcaJ' >>> ...and now to make it all about 'me': If such was not sufficiently emphasised, do I need to review the topic to improve coverage? Now the boot is on the other foot: perhaps I should be using the program design advice (begin the decision tree by looking at the stride's direction) and apply that to proof-reading my talk's coverage to ensure that each 'half' of the 'network tree' is equally-well/sufficiently covered! Which brings us to:- >> and first splitting the implementation's decision-tree into two paths, >> according to whether the stride is positive or negative, before getting >> into 'the nitty-gritty'. > > That I had already done. Great! ... > Yes, send me your tests! (``Caveat emptor'' noted.) (I had included all > tests that appeared in this thread, but had missed, for example, "Jack > Brandom"[-100 : 100]. Didn't occur to me this wouldn't blow an > exception.) (and here's the justification for the earlier rave about using real email addresses - I should be sending this to you-alone, and not 'cluttering-up' the entire list (and its archive)!) <<< # would normally put TDD/unit tests in separate file from 'real code' """Three-way tests comparing: 1 the output of the slice simulation function (under test) 2 the expected output string 3 the actual output from a slice """ name = "Jack Brandom" # assert web.ref: https://www.simplilearn.com/tutorials/python-tutorial/assert-in-python (in case needed) assert ( my_slice( name, lower_bound=0, upper_bound=12 ) == 'Jack Brandom' == name[ 0:12 ] ) assert ( my_slice( name, upper_bound=6 ) == 'Jack B' == name[ :6 ] ) assert ( my_slice( name, lower_bound=5 ) == 'Brandom' == name[ 5: ] ) assert ( my_slice( name ) == 'Jack Brandom' == name[ : ] ) assert ( my_slice( name, stride=2 ) == 'Jc rno' == name[ ::2 ] ) assert ( my_slice( name, lower_bound=-100, upper_bound=+100 ) == 'Jack Brandom' == name[ -100:100 ] ) assert ( my_slice( name, upper_bound=4 ) == 'Jack' == name[ :4 ] ) assert ( my_slice( name, upper_bound=-8 ) == 'Jack' == name[ :-8 ] ) assert ( my_slice( name, lower_bound=5 ) == 'Brandom' == name[ 5: ] ) assert ( my_slice( name, lower_bound=-7 ) == 'Brandom' == name[ -7: ] ) assert ( my_slice( name, lower_bound=1, upper_bound=9 ) == 'ack Bran' == name[ 1:9 ] ) assert ( my_slice( name, lower_bound=-11, upper_bound=-3 ) == 'ack Bran' == name[ -11:-3 ] ) assert ( my_slice( name, lower_bound=3, stride=-1 ) == 'kcaJ' == name[ 3::-1 ] ) assert ( my_slice( name, lower_bound=-9, stride=-1 ) == 'kcaJ' == name[ -9::-1 ] ) assert ( my_slice( name, upper_bound=4, stride=-1 ) == 'modnarB' == name[ :4:-1 ] ) assert ( my_slice( name, upper_bound=-8, stride=-1 ) == 'modnarB' == name[ :-8:-1 ] ) assert ( my_slice( name, lower_bound=6, upper_bound=2, stride=-1 ) == 'rB k' == name[ 6:2:-1 ] ) assert ( my_slice( name, lower_bound=-6, upper_bound=-10, stride=-1 ) == 'rB k' == name[ -6:-10:-1 ] ) >>> > Thank you so much. and thank you for helping to improve my talk... -- Regards, =dn From PythonList at DancesWithMice.info Wed Aug 11 21:17:32 2021 From: PythonList at DancesWithMice.info (dn) Date: Thu, 12 Aug 2021 13:17:32 +1200 Subject: on slices, negative indices, which are the equivalent procedures? In-Reply-To: <4vi8hg1tfcd2vsrchgpnbpf9a9l7acf7rl@4ax.com> References: <86sfznhk1f.fsf@example.com> <86wnos9ge8.fsf@jevedi.com> <4vi8hg1tfcd2vsrchgpnbpf9a9l7acf7rl@4ax.com> Message-ID: On 12/08/2021 10.32, Dennis Lee Bieber wrote: > On Wed, 11 Aug 2021 11:59:11 -0300, Jack Brandom > declaimed the following: >> Where are these production rules coming from? They're not at >> https://docs.python.org/3/reference/grammar.html >> The word ``stride'' doesn't appear in this grammar. > > Possibly from older versions of the grammar, before simplification to > just . Originally, the "stride" term was added in response to > requests from the numerical library developers (NumPy seems to be the > survivor of that cluster). At the time, it wasn't envisioned to be usable > with regular Python objects. > > https://en.wikipedia.org/wiki/Array_slicing#1991:_Python > """ > The stride syntax (nums[1:5:2]) was introduced in the second half of the > 1990s, as a result of requests put forward by scientific users in the > Python "matrix-SIG" (special interest group). > """ > > As for the grammar... Would you prefer that from 2.7? > > trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME > subscriptlist: subscript (',' subscript)* [','] > subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] > sliceop: ':' [test] > > test: or_test ['if' or_test 'else' test] | lambdef > or_test: and_test ('or' and_test)* > and_test: not_test ('and' not_test)* > not_test: 'not' not_test | comparison Are you trying to give us nightmares @wulfraed? Yes, the somewhat piecemeal coverage(s) are explained by changes over time, and the different applications folk might apply or differing motivations of the people involved. I've been trying to remember if we had negative-steps in FORTRAN do-loops especially once the capability to define subscripting-ranges came 'in' (but can't be bothered researching further). If it was available, or available within other, older languages, then might this explain Python's adoption? It is quite plain (Ref.Man 6.3.3 and 3.2) that initially the plans for stride/step did not include the negative 'direction'. Perhaps the initial coders thought: 'while I'm doing this, adding ... will be easy to do', aka "famous last words", see also "YAGNI". Negative-stepping comes-across as a bit of a party-trick. I wonder if anyone can offer a (professional) application? Similarly, when adding a __getitem__() to a custom-class, has anyone had need to implement/account for negative-stepping, to achieve some purpose? PS I'm waiting (with bated breath*) for @Chris' bared teeth... * or is that "baited"? -- Regards, =dn From stephen_tucker at sil.org Thu Aug 12 04:57:33 2021 From: stephen_tucker at sil.org (Stephen Tucker) Date: Thu, 12 Aug 2021 09:57:33 +0100 Subject: Is there a better way to create a list of None objects? Message-ID: Hi, I thought I'd share the following piece of code that I have recently written (a) to check that what I have done is reasonable - even optimum, (b) to inform others who might be wanting to do similar things, and (c) to invite comment from the community. ------------------------------------------- # # Yes: Create an empty list of Band Limits for this language # # Note. The rather complicated logic on the right-hand side of the # assignment below is used here because none of the following # alternatives had the desired effect: # # Logic Effect # # [None * 8] TypeError: unsupported operand type(s) for *: ... # [(None) * 8] TypeError: unsupported operand type(s) for *: ... # [((None)) * 8] TypeError: unsupported operand type(s) for *: ... # [(None,) * 8] [(None, None, None, None, None, None, None, None)] # list ((None) * 8) TypeError: unsupported operand type(s) for *: ... # diclll_BLim [thisISO_] = list ((None,) * 8) ------------------------------------------- Thanks in anticipation. Stephen Tucker. From rosuav at gmail.com Thu Aug 12 05:11:06 2021 From: rosuav at gmail.com (Chris Angelico) Date: Thu, 12 Aug 2021 19:11:06 +1000 Subject: Is there a better way to create a list of None objects? In-Reply-To: References: Message-ID: On Thu, Aug 12, 2021 at 6:59 PM Stephen Tucker wrote: > > Hi, > > I thought I'd share the following piece of code that I have recently written > (a) to check that what I have done is reasonable - even optimum, > (b) to inform others who might be wanting to do similar things, and > (c) to invite comment from the community. > > ------------------------------------------- > > # > > # Yes: Create an empty list of Band Limits for this language > > # > > # Note. The rather complicated logic on the right-hand side of the > > # assignment below is used here because none of the following > > # alternatives had the desired effect: > > # > > # Logic Effect > > # > > # [None * 8] TypeError: unsupported operand type(s) for *: ... > > # [(None) * 8] TypeError: unsupported operand type(s) for *: ... > > # [((None)) * 8] TypeError: unsupported operand type(s) for *: ... > > # [(None,) * 8] [(None, None, None, None, None, None, None, None)] > > # list ((None) * 8) TypeError: unsupported operand type(s) for *: ... > > # > > diclll_BLim [thisISO_] = list ((None,) * 8) > Why not just: [None] * 8 ? ChrisA From m.dartiailh at gmail.com Thu Aug 12 05:22:37 2021 From: m.dartiailh at gmail.com (Matthieu Dartiailh) Date: Thu, 12 Aug 2021 11:22:37 +0200 Subject: Is there a better way to create a list of None objects? In-Reply-To: References: Message-ID: <9201775c-e6eb-63e5-bd68-6fc9111fcb03@gmail.com> You can achieve the same result by writing: [None] * 8 Comparing both cases in IPython I get: In [1]: %timeit list((None,)*8) 110 ns ? 0.785 ns per loop (mean ? std. dev. of 7 runs, 10000000 loops each) In [2]: %timeit [None] * 8 88.2 ns ? 0.432 ns per loop (mean ? std. dev. of 7 runs, 10000000 loops each) So the list multiplication appears a bit faster. Best Matthieu Le 8/12/2021 ? 10:57 AM, Stephen Tucker a ?crit?: > Hi, > > I thought I'd share the following piece of code that I have recently written > (a) to check that what I have done is reasonable - even optimum, > (b) to inform others who might be wanting to do similar things, and > (c) to invite comment from the community. > > ------------------------------------------- > > # > > # Yes: Create an empty list of Band Limits for this language > > # > > # Note. The rather complicated logic on the right-hand side of the > > # assignment below is used here because none of the following > > # alternatives had the desired effect: > > # > > # Logic Effect > > # > > # [None * 8] TypeError: unsupported operand type(s) for *: ... > > # [(None) * 8] TypeError: unsupported operand type(s) for *: ... > > # [((None)) * 8] TypeError: unsupported operand type(s) for *: ... > > # [(None,) * 8] [(None, None, None, None, None, None, None, None)] > > # list ((None) * 8) TypeError: unsupported operand type(s) for *: ... > > # > > diclll_BLim [thisISO_] = list ((None,) * 8) > > > ------------------------------------------- > > Thanks in anticipation. > > Stephen Tucker. From stephen_tucker at sil.org Thu Aug 12 10:26:05 2021 From: stephen_tucker at sil.org (Stephen Tucker) Date: Thu, 12 Aug 2021 15:26:05 +0100 Subject: Is there a better way to create a list of None objects? In-Reply-To: <9201775c-e6eb-63e5-bd68-6fc9111fcb03@gmail.com> References: <9201775c-e6eb-63e5-bd68-6fc9111fcb03@gmail.com> Message-ID: Thanks for this feedback, Chris, Matthieu. Both are spot on - and thanks for the timing comparison, Matthieu. I suppose I didn't think to try the solution you suggest because I didn't think that I would end up with a single list, but 8 of them. OK, I'll stop wriggling. Stephen. On Thu, Aug 12, 2021 at 10:22 AM Matthieu Dartiailh wrote: > You can achieve the same result by writing: > [None] * 8 > > Comparing both cases in IPython I get: > > In [1]: %timeit list((None,)*8) > 110 ns ? 0.785 ns per loop (mean ? std. dev. of 7 runs, 10000000 loops > each) > > In [2]: %timeit [None] * 8 > 88.2 ns ? 0.432 ns per loop (mean ? std. dev. of 7 runs, 10000000 loops > each) > > So the list multiplication appears a bit faster. > > Best > > Matthieu > > Le 8/12/2021 ? 10:57 AM, Stephen Tucker a ?crit : > > Hi, > > > > I thought I'd share the following piece of code that I have recently > written > > (a) to check that what I have done is reasonable - even optimum, > > (b) to inform others who might be wanting to do similar things, and > > (c) to invite comment from the community. > > > > ------------------------------------------- > > > > # > > > > # Yes: Create an empty list of Band Limits for this language > > > > # > > > > # Note. The rather complicated logic on the right-hand side of the > > > > # assignment below is used here because none of the following > > > > # alternatives had the desired effect: > > > > # > > > > # Logic Effect > > > > # > > > > # [None * 8] TypeError: unsupported operand type(s) for *: ... > > > > # [(None) * 8] TypeError: unsupported operand type(s) for *: ... > > > > # [((None)) * 8] TypeError: unsupported operand type(s) for *: ... > > > > # [(None,) * 8] [(None, None, None, None, None, None, None, None)] > > > > # list ((None) * 8) TypeError: unsupported operand type(s) for *: ... > > > > # > > > > diclll_BLim [thisISO_] = list ((None,) * 8) > > > > > > ------------------------------------------- > > > > Thanks in anticipation. > > > > Stephen Tucker. > > -- > https://mail.python.org/mailman/listinfo/python-list > From chenghuitan02 at gmail.com Wed Aug 11 22:31:52 2021 From: chenghuitan02 at gmail.com (Tan Jane) Date: Thu, 12 Aug 2021 10:31:52 +0800 Subject: FW: Troubleshoot python app launch In-Reply-To: <313490B0-E1C3-452F-A4FE-ECC742EC36A8@hxcore.ol> References: <313490B0-E1C3-452F-A4FE-ECC742EC36A8@hxcore.ol> Message-ID: <7252A5F9-40FC-4EDF-B34F-E2BB78572BF1@hxcore.ol> From: [1]Tan Jane Sent: Wednesday, 11 August 2021 7:48 PM To: [2]python-list at python.org Subject: Troubleshoot python app launch Hi, I encountered attached screenshot issue while launching the python application downloaded for windows. Please advice on the above. Thanks, Jane Sent from [3]Mail for Windows 10 References Visible links 1. mailto:chenghuitan02 at gmail.com 2. mailto:python-list at python.org 3. https://go.microsoft.com/fwlink/?LinkId=550986 From wlfraed at ix.netcom.com Thu Aug 12 11:13:58 2021 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Thu, 12 Aug 2021 11:13:58 -0400 Subject: on slices, negative indices, which are the equivalent procedures? References: <86sfznhk1f.fsf@example.com> <86wnos9ge8.fsf@jevedi.com> <4vi8hg1tfcd2vsrchgpnbpf9a9l7acf7rl@4ax.com> Message-ID: On Thu, 12 Aug 2021 13:17:32 +1200, dn via Python-list declaimed the following: >I've been trying to remember if we had negative-steps in FORTRAN >do-loops especially once the capability to define subscripting-ranges >came 'in' (but can't be bothered researching further). If it was >available, or available within other, older languages, then might this >explain Python's adoption? > As part of the DO loop, FORTRAN did allow decrementing -- but one also had then to put the start-end in correct order... DO 10 I = 32, 0, -1 -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From hrouselle at jevedi.com Thu Aug 12 11:09:58 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Thu, 12 Aug 2021 12:09:58 -0300 Subject: some problems for an introductory python test References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86lf599zse.fsf@jevedi.xotimo> <868s18b1p7.fsf@jevedi.com> Message-ID: <868s16zol5.fsf@jevedi.com> Chris Angelico writes: [...] >> > [1] And boy oh boy was that good fun. The OS/2 Presentation Manager >> > had a wealth of power available. Good times, sad that's history now. >> >> I know OS/2 only by name. I never had the pleasure of using it. In >> fact, I don't even know how it looks. I must be a little younger than >> you are. But not too younger because I kinda remember its name. Was it >> a system that might have thought of competing against Microsoft Windows? >> :-) That's what my memory tells me about it. > > History lesson! > > Once upon a time, IBM and Microsoft looked at what Intel was > producing, and went, hey, we need to design an operating system that > can take advantage of the fancy features of this 80286 thing. So they > collaborate on this plan to make a 16-bit protected mode OS. > Unfortunately, things didn't work out too well, partly because this > was when Microsoft was at its most monopolistic, and they ended up > parting company. IBM continued to make OS/2, but Microsoft took their > part of the code and made Windows NT out of it. How is it possible that Microsoft would take part of the code of OS/2? Did IBM just hand it to them? > (Aside: Windows NT's 16-bit applications and OS/2's 16-bit > applications were actually identical and compatible. Unfortunately, > Win32 introduced a very new API, so as soon as everyone moved to > 32-bit everything, the schism became problematic. But it was actually > possible to package up a single .EXE file with a 16-bit MS-DOS loader, > a Win32 loader, and an OS/2 32-bit loader, all happily coexisting. Beautiful. :-) So if all libraries were around in each system, they had perfect compatibility? > In the latter half of the 1990s, Windows came in three broad flavours: > the 16-bit Windows 3.x line, which ran purely on top of DOS; the > 32-bit Windows 95 line, which was the "home" OS and had to be heavily > compatible with Windows 3, but still doing more things; and the > Windows NT line, which was aimed at businesses. OS/2 was a viable > option for businesses, but almost nobody took it seriously as a home > OS. And Microsoft was using its marketing machine to push Windows > fairly hard, so most people went that way. > > OS/2 had all kinds of amazing features (for its time). The default > file system, HPFS ("High Performance File System"... IBM was good at > many things, but imaginative naming wasn't one of them), did a > spectacular job of maintaining reliability and performance on the > ever-growing hard disks of the time. Yes, it coped remarkably well, > even on *gigantic* drives that could carry, ooh, an entire gigabyte of > data! I'm not kidding! We even had a drive that had TWO gigabytes of > space, and HPFS managed it beautifully! Plus, it had this fancy > concept of "extended attributes"; on older systems (like MS-DOS's > "FAT" family), a file might be Read-Only, Hidden, a System file, or > needing to be Archived, and that was it - but on HPFS, you could > attach arbitrary data like "File type: DeScribe Word Processor" or > "Double click action: Run CASMake.cmd". This allowed the GUI to store > all kinds of information *on the file itself* instead of needing > hidden files (or, in Windows' case, the registry) to track that kind > of thing. Yeah, that's kinda nice. Isn't that a UNIX design? A file is a sequence of bytes? Users decide what to put in them? So OS/2 was taking advantage of that to integrate it well with the system. Windows was doing the same, but integrating the system with files in odd ways --- such as a registry record to inform the system which programs open which files? (That does sound more messy.) UNIX's execve() is able to read the first line of an executable and invoke its interpreter. I guess OS/2 was doing precisely that in a different way? > The default command interpreter and shell on OS/2 was fairly primitive > by today's standards, and was highly compatible with the MS-DOS one, > but it also had the ability to run REXX scripts. REXX was *way* ahead > of its time. It's a shell language but remarkably well suited to > building GUIs and other tools (seriously, can you imagine designing a > GUI entirely in a bash script??). I cannot imagine. I always wondered what REXX was about --- I saw programs sometimes written in some website whose name is something like Rosetta Code. REXX looked so weird. (``Who would program in that?'') But I see now there is a context to it. > It had features that we'd consider fairly normal or even primitive by > Python's standards, but back then, Python was extremely new and didn't > really have very much mindshare. REXX offered arbitrary-precision > arithmetic, good databasing support, a solid C API that made it easy > to extend, integrations with a variety of other systems... this was > good stuff for its day. (REXX is still around, but these days, I'd > rather use Python.) Yeah, REXX looks horrible at first. But arbitrary-precision is definitely very attractive. I never liked to deal with floating-point. > I mentioned the Presentation Manager, because it was one of the best > parts of running OS/2. The kernel was decent, but it was the graphical > shell that was the real pleasure to work with. Probably the most > notable feature, by today's standards, was that it had a single input > queue. If you press a series of keys, they'd go into a global queue, > and the application that has focus would get the first one. When that > key has been handled, the application that has focus would get the > next key from the queue. This means that, if the response to a > keystroke is to change focus, then *even in a slow and lagged out > system*, subsequent keys WOULD be sent to the new target window. That > was AWESOME, and I really miss it. Except that I also don't. Because > if a single application is having issues, now your entire keyboard and > mouse is locked up... which kinda slightly sucks. Good luck resolving > that problem. (We had some neat tools like WatchCat that could get > around the single input queue via interrupt signals, and regain > control. But it was still problematic.) Wow, I kinda feel the same as you here. I think this justifies perhaps using a hardware solution. (Crazy idea?! Lol.) Maybe machine and OS could have a desktop-version that would have a hardware that could effectively be like a second keyboard --- a button. So our keywords would have a button that we press it, we could interrupt the OS to handle such lock-up more gracefully. I suppose this is expensive, complex and so on. But at the same time, it could be worth it. > So, yeah. It was spectacular in its day.... but it kinda got left > behind as the world moved on. These days, instead of running REXX code > on OS/2 in a system that uses eight-bit text for most things, I use > Python on Linux and full Unicode. But OS/2 was an important part of > history, both my own personal journey, and the history of the world of > PCs. Very nice. Thanks a lot for sharing. I care a lot about such histories. In fact, if you could point out from the top of your head the best reference on the facts you mentioned here, I would love to write it down for future reference. (You probably read books that perhaps explained how the queue of windows messages worked et cetera.) Thank you! From wlfraed at ix.netcom.com Thu Aug 12 11:43:51 2021 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Thu, 12 Aug 2021 11:43:51 -0400 Subject: Is there a better way to create a list of None objects? References: Message-ID: On Thu, 12 Aug 2021 09:57:33 +0100, Stephen Tucker declaimed the following: > ># Logic Effect > ># > ># [None * 8] TypeError: unsupported operand type(s) for *: ... > ># [(None) * 8] TypeError: unsupported operand type(s) for *: ... > ># [((None)) * 8] TypeError: unsupported operand type(s) for *: ... > ># [(None,) * 8] [(None, None, None, None, None, None, None, None)] > ># list ((None) * 8) TypeError: unsupported operand type(s) for *: ... > In all the above, you've put the *8 INSIDE the list structure. You "working" example is actually creating a TUPLE stored (as the only element) inside a LIST. >>> [None] * 8 [None, None, None, None, None, None, None, None] >>> Creates a LIST of 8 elements, each being None. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From python at mrabarnett.plus.com Thu Aug 12 12:45:29 2021 From: python at mrabarnett.plus.com (MRAB) Date: Thu, 12 Aug 2021 17:45:29 +0100 Subject: FW: Troubleshoot python app launch In-Reply-To: <7252A5F9-40FC-4EDF-B34F-E2BB78572BF1@hxcore.ol> References: <313490B0-E1C3-452F-A4FE-ECC742EC36A8@hxcore.ol> <7252A5F9-40FC-4EDF-B34F-E2BB78572BF1@hxcore.ol> Message-ID: <6dc2e1c1-2a77-d26d-b0df-3a28f40d17a8@mrabarnett.plus.com> On 2021-08-12 03:31, Tan Jane wrote: > > > From: [1]Tan Jane > Sent: Wednesday, 11 August 2021 7:48 PM > To: [2]python-list at python.org > Subject: Troubleshoot python app launch > > > > Hi, > > > > I encountered attached screenshot issue while launching the python > application downloaded for windows. > > > > Please advice on the above. > This list strips attachments. Please copy and paste the error. From rosuav at gmail.com Thu Aug 12 14:41:42 2021 From: rosuav at gmail.com (Chris Angelico) Date: Fri, 13 Aug 2021 04:41:42 +1000 Subject: some problems for an introductory python test In-Reply-To: <868s16zol5.fsf@jevedi.com> References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86lf599zse.fsf@jevedi.xotimo> <868s18b1p7.fsf@jevedi.com> <868s16zol5.fsf@jevedi.com> Message-ID: On Fri, Aug 13, 2021 at 2:15 AM Hope Rouselle wrote: > > Chris Angelico writes: > > > History lesson! > > > > Once upon a time, IBM and Microsoft looked at what Intel was > > producing, and went, hey, we need to design an operating system that > > can take advantage of the fancy features of this 80286 thing. So they > > collaborate on this plan to make a 16-bit protected mode OS. > > Unfortunately, things didn't work out too well, partly because this > > was when Microsoft was at its most monopolistic, and they ended up > > parting company. IBM continued to make OS/2, but Microsoft took their > > part of the code and made Windows NT out of it. > > How is it possible that Microsoft would take part of the code of OS/2? > Did IBM just hand it to them? I presume both companies had all of the code. It was a matter of licensing, though. There were a few components that were saddled with awkward restrictions due to the dual ownership (for instance, HPFS386 was Microsoft-controlled, but vanilla HPFS was fine - kinda like the difference between LZW and LZ77). > > (Aside: Windows NT's 16-bit applications and OS/2's 16-bit > > applications were actually identical and compatible. Unfortunately, > > Win32 introduced a very new API, so as soon as everyone moved to > > 32-bit everything, the schism became problematic. But it was actually > > possible to package up a single .EXE file with a 16-bit MS-DOS loader, > > a Win32 loader, and an OS/2 32-bit loader, all happily coexisting. > > Beautiful. :-) So if all libraries were around in each system, they had > perfect compatibility? The 16-bit loaders were fine, but the 32-bit loaders were different, so this trick basically meant having three different copies of the code wrapped up in a single executable. > > Plus, it had this fancy > > concept of "extended attributes"; on older systems (like MS-DOS's > > "FAT" family), a file might be Read-Only, Hidden, a System file, or > > needing to be Archived, and that was it - but on HPFS, you could > > attach arbitrary data like "File type: DeScribe Word Processor" or > > "Double click action: Run CASMake.cmd". This allowed the GUI to store > > all kinds of information *on the file itself* instead of needing > > hidden files (or, in Windows' case, the registry) to track that kind > > of thing. > > Yeah, that's kinda nice. Isn't that a UNIX design? A file is a > sequence of bytes? Users decide what to put in them? So OS/2 was > taking advantage of that to integrate it well with the system. Windows > was doing the same, but integrating the system with files in odd ways > --- such as a registry record to inform the system which programs open > which files? (That does sound more messy.) Something like that, but with a lot more metadata. Modern OSes don't seem to work that way any more. > UNIX's execve() is able to read the first line of an executable and > invoke its interpreter. I guess OS/2 was doing precisely that in a > different way? Kinda, but instead of having the choice of interpreter be inside the file contents itself, the choice was in the file's metadata. Still part of the file, but if you open and read the file, it isn't any different. > > The default command interpreter and shell on OS/2 was fairly primitive > > by today's standards, and was highly compatible with the MS-DOS one, > > but it also had the ability to run REXX scripts. REXX was *way* ahead > > of its time. It's a shell language but remarkably well suited to > > building GUIs and other tools (seriously, can you imagine designing a > > GUI entirely in a bash script??). > > I cannot imagine. I always wondered what REXX was about --- I saw > programs sometimes written in some website whose name is something like > Rosetta Code. REXX looked so weird. (``Who would program in that?'') > But I see now there is a context to it. Yeah. It was a strange choice by today's standards, but back then, most of my GUI programs were written in REXX. https://en.wikipedia.org/wiki/VX-REXX http://www.edm2.com/0206/vrexx.html (There were other tools too - VisPro REXX, VREXX, DrDialog, and various others - but VX-REXX was where most of my dev work happened.) > > Probably the most > > notable feature, by today's standards, was that it had a single input > > queue. ... This means that, if the response to a > > keystroke is to change focus, then *even in a slow and lagged out > > system*, subsequent keys WOULD be sent to the new target window. That > > was AWESOME, and I really miss it. Except that I also don't. Because > > if a single application is having issues, now your entire keyboard and > > mouse is locked up... which kinda slightly sucks. Good luck resolving > > that problem. (We had some neat tools like WatchCat that could get > > around the single input queue via interrupt signals, and regain > > control. But it was still problematic.) > > Wow, I kinda feel the same as you here. I think this justifies perhaps > using a hardware solution. (Crazy idea?! Lol.) uhhh........ Yes. Very crazy idea. Can't imagine why anyone would ever think about doing that. Certainly nobody in his right mind would have WatchCat listening on the serial port's Ring Indicator interrupt, and then grab a paperclip to bridge the DTR and RI pins on an otherwise-unoccupied serial port on the back of the PC. (The DTR pin was kept high by the PC, and could therefore be used as an open power pin to bring the RI high.) If you're curious, it's pins 4 and 9 - diagonally up and in from the short corner. http://www.usconverters.com/index.php?main_page=page&id=61&chapter=0 And of COURSE nobody would ever take an old serial mouse, take the ball out of it, and turn it into a foot-controlled signal... although that wasn't for WatchCat, that was for clipboard management between my app and a Windows accounting package that we used. But that's a separate story. > Maybe machine and OS > could have a desktop-version that would have a hardware that could > effectively be like a second keyboard --- a button. So our keywords > would have a button that we press it, we could interrupt the OS to > handle such lock-up more gracefully. I suppose this is expensive, > complex and so on. But at the same time, it could be worth it. SysRq should theoretically be that. (That's Alt+PrtSc on a lot of keyboards.) I'm not sure how it could best be handled though. It might be that today's GUI systems (X11, Wayland, Cocoa, Win32, etc) just wouldn't work with a single input queue. Would be curious to see if any modern OS/GUI pair has a synchronous input queue like that. > > So, yeah. It was spectacular in its day.... but it kinda got left > > behind as the world moved on. These days, instead of running REXX code > > on OS/2 in a system that uses eight-bit text for most things, I use > > Python on Linux and full Unicode. But OS/2 was an important part of > > history, both my own personal journey, and the history of the world of > > PCs. > > Very nice. Thanks a lot for sharing. I care a lot about such > histories. In fact, if you could point out from the top of your head > the best reference on the facts you mentioned here, I would love to > write it down for future reference. (You probably read books that > perhaps explained how the queue of windows messages worked et cetera.) > > Thank you! Thank you for asking questions about it! Aside from making me feel old (which, let's face it, is kinda inevitable), it's great to dig through some of the history and a few of the very different ways things have been done. References, unfortunately, are a bit hard to share, since they're mostly dead-tree books, plus a small number of IPF documents (a format kinda like man pages, but they get compiled) which have probably been lost by now. Oh, plus a lot of "My dad told me", which is a bit hard to point anyone else to :) But if you want to delve into things today, I would recommend using Wikipedia or whatever the almighty Google shows up, neither of which was available back then, but both of which have vast information available to you. Some useful topics: * Single (or Synchronous) Input Queue * CORBA (the system for cross-language subclassing of PM classes) * The OS/2 Presentation Manager * 80386 Protected Mode * DBCS (early multilanguage support - appallingly inferior to Unicode, but better than nothing) * REXX, VX-REXX, VPREXX, VREXX * DB2 (IBM's flagship database both then and now; spectacular even back then, although slow at times) Python *was* available on OS/2 back then, but not heavily supported. It might be interesting to compare the early versions of Python to the other tools available, but probably more useful to compare the 1990s tools to modern Python on modern OSes and see how far the world has come. ChrisA From grant.b.edwards at gmail.com Thu Aug 12 13:52:42 2021 From: grant.b.edwards at gmail.com (Grant Edwards) Date: Thu, 12 Aug 2021 17:52:42 -0000 (UTC) Subject: some problems for an introductory python test References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86lf599zse.fsf@jevedi.xotimo> <868s18b1p7.fsf@jevedi.com> <868s16zol5.fsf@jevedi.com> Message-ID: On 2021-08-12, Hope Rouselle wrote: >> OS/2 had all kinds of amazing features (for its time). [...] Plus, >> it had this fancy concept of "extended attributes"; on older >> systems (like MS-DOS's "FAT" family), a file might be Read-Only, >> Hidden, a System file, or needing to be Archived, and that was it - >> but on HPFS, you could attach arbitrary data like "File type: >> DeScribe Word Processor" or "Double click action: Run >> CASMake.cmd". This allowed the GUI to store all kinds of >> information *on the file itself* instead of needing hidden files >> (or, in Windows' case, the registry) to track that kind of thing. > > Yeah, that's kinda nice. Isn't that a UNIX design? A file is a > sequence of bytes? Users decide what to put in them? I think what he's talking about is allowing the user to attach arbitrary _metadata_ to the file -- metadata that exists separately and independently from the normal data that's just a "sequence of bytes". IOW, something similar to the "resource fork" that MacOS used to have. https://en.wikipedia.org/wiki/Resource_fork > So OS/2 was taking advantage of that to integrate it well with the > system. Windows was doing the same, but integrating the system with > files in odd ways --- such as a registry record to inform the system > which programs open which files? (That does sound more messy.) Windows never had filesystems that supported metadata like OS/2 and MacOS did. The registry was an ugly hack that attempted (very poorly) to make up for that lack of metadata. > UNIX's execve() is able to read the first line of an executable and > invoke its interpreter. I guess OS/2 was doing precisely that in a > different way? No, that's not at all the same thing. The #! line is part of the normal file data. It's part of the 'sequence of bytes'. Metadata maintained by Unix filesystems comprises a very limited and pre-defined set of attributes present in the inode. -- Grant From rosuav at gmail.com Thu Aug 12 15:14:10 2021 From: rosuav at gmail.com (Chris Angelico) Date: Fri, 13 Aug 2021 05:14:10 +1000 Subject: some problems for an introductory python test In-Reply-To: References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86lf599zse.fsf@jevedi.xotimo> <868s18b1p7.fsf@jevedi.com> <868s16zol5.fsf@jevedi.com> Message-ID: On Fri, Aug 13, 2021 at 5:03 AM Grant Edwards wrote: > > On 2021-08-12, Hope Rouselle wrote: > > >> OS/2 had all kinds of amazing features (for its time). [...] Plus, > >> it had this fancy concept of "extended attributes"; on older > >> systems (like MS-DOS's "FAT" family), a file might be Read-Only, > >> Hidden, a System file, or needing to be Archived, and that was it - > >> but on HPFS, you could attach arbitrary data like "File type: > >> DeScribe Word Processor" or "Double click action: Run > >> CASMake.cmd". This allowed the GUI to store all kinds of > >> information *on the file itself* instead of needing hidden files > >> (or, in Windows' case, the registry) to track that kind of thing. > > > > Yeah, that's kinda nice. Isn't that a UNIX design? A file is a > > sequence of bytes? Users decide what to put in them? > > I think what he's talking about is allowing the user to attach > arbitrary _metadata_ to the file -- metadata that exists separately > and independently from the normal data that's just a "sequence of > bytes". IOW, something similar to the "resource fork" that MacOS used > to have. https://en.wikipedia.org/wiki/Resource_fork Correct. OS/2's EAs are name/value pairs (with the value potentially being a set of values - think how a Python dict maps keys to values, but the values could be lists), with a few names having significance to the system, like .TYPE and .LONGNAME (used on file systems that didn't support longnames - yes, that's possible, since EAs could be stored in a hidden file on a FAT disk). > > So OS/2 was taking advantage of that to integrate it well with the > > system. Windows was doing the same, but integrating the system with > > files in odd ways --- such as a registry record to inform the system > > which programs open which files? (That does sound more messy.) > > Windows never had filesystems that supported metadata like OS/2 and > MacOS did. The registry was an ugly hack that attempted (very poorly) > to make up for that lack of metadata. Very poor indeed - it was very very common back then for Windows programs to blat themselves all over the registry and then leave it all behind when you nuke that thing. With EAs, it's all part of the file itself and will be cleaned up by a simple directory removal. ChrisA From python at mrabarnett.plus.com Thu Aug 12 15:54:01 2021 From: python at mrabarnett.plus.com (MRAB) Date: Thu, 12 Aug 2021 20:54:01 +0100 Subject: some problems for an introductory python test In-Reply-To: References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86lf599zse.fsf@jevedi.xotimo> <868s18b1p7.fsf@jevedi.com> <868s16zol5.fsf@jevedi.com> Message-ID: <4c9de5d7-97ff-65b0-8669-8dc17f229fd0@mrabarnett.plus.com> On 2021-08-12 18:52, Grant Edwards wrote: > On 2021-08-12, Hope Rouselle wrote: > >>> OS/2 had all kinds of amazing features (for its time). [...] Plus, >>> it had this fancy concept of "extended attributes"; on older >>> systems (like MS-DOS's "FAT" family), a file might be Read-Only, >>> Hidden, a System file, or needing to be Archived, and that was it - >>> but on HPFS, you could attach arbitrary data like "File type: >>> DeScribe Word Processor" or "Double click action: Run >>> CASMake.cmd". This allowed the GUI to store all kinds of >>> information *on the file itself* instead of needing hidden files >>> (or, in Windows' case, the registry) to track that kind of thing. >> >> Yeah, that's kinda nice. Isn't that a UNIX design? A file is a >> sequence of bytes? Users decide what to put in them? > > I think what he's talking about is allowing the user to attach > arbitrary _metadata_ to the file -- metadata that exists separately > and independently from the normal data that's just a "sequence of > bytes". IOW, something similar to the "resource fork" that MacOS used > to have. https://en.wikipedia.org/wiki/Resource_fork > >> So OS/2 was taking advantage of that to integrate it well with the >> system. Windows was doing the same, but integrating the system with >> files in odd ways --- such as a registry record to inform the system >> which programs open which files? (That does sound more messy.) > > Windows never had filesystems that supported metadata like OS/2 and > MacOS did. The registry was an ugly hack that attempted (very poorly) > to make up for that lack of metadata. > FYI, NTFS does support Alternate Data Streams. >> UNIX's execve() is able to read the first line of an executable and >> invoke its interpreter. I guess OS/2 was doing precisely that in a >> different way? > > No, that's not at all the same thing. The #! line is part of the > normal file data. It's part of the 'sequence of bytes'. Metadata > maintained by Unix filesystems comprises a very limited and > pre-defined set of attributes present in the inode. > From wlfraed at ix.netcom.com Thu Aug 12 15:56:04 2021 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Thu, 12 Aug 2021 15:56:04 -0400 Subject: some problems for an introductory python test References: <86lf599zse.fsf@jevedi.xotimo> <868s18b1p7.fsf@jevedi.com> <868s16zol5.fsf@jevedi.com> Message-ID: <29qahglb1bebs1fmcllvrejqh67mpth48e@4ax.com> On Thu, 12 Aug 2021 12:09:58 -0300, Hope Rouselle declaimed the following: >How is it possible that Microsoft would take part of the code of OS/2? >Did IBM just hand it to them? > Because IBM subcontracted (IE: "paid") M$ to create an OS with XYZ features for their latest PC (under supervision of IBM design team).. https://en.wikipedia.org/wiki/OS/2 IBM owned the rights to OS/2, but it was written, for the most part, by M$ in parallel with M$ own "Windows" 16-bit OS. > >Yeah, that's kinda nice. Isn't that a UNIX design? A file is a >sequence of bytes? Users decide what to put in them? So OS/2 was >taking advantage of that to integrate it well with the system. Windows >was doing the same, but integrating the system with files in odd ways >--- such as a registry record to inform the system which programs open >which files? (That does sound more messy.) > Not really -- Have you looked at what a hash Linux graphical interfaces require to associate file types with how to open said files? On my Debian (VirtualBox) there is: wulfraed at debian:~$ cat ~/.config/mimeapps.list [Added Associations] text/html=firefox-esr.desktop; text/plain=gvim.desktop; x-scheme-handler/http=exo-web-browser.desktop x-scheme-handler/https=exo-web-browser.desktop x-scheme-handler/mailto=exo-mail-reader.desktop application/xml=gvim.desktop; text/x-scheme=gvim.desktop; application/vnd.kde.kxmlguirc=gvim.desktop; text/x-python=gvim.desktop; application/x-shellscript=gvim.desktop; [Default Applications] wulfraed at debian:~$ ... and all these wulfraed at debian:~$ ls /usr/share/applications atril.desktop panel-desktop-handler.desktop claws-mail.desktop panel-preferences.desktop ... debian-uxterm.desktop python3.7.desktop ... org.thonny.Thonny.desktop xsane.desktop org.xfce.Parole.desktop wulfraed at debian:~$ wulfraed at debian:~$ cat /usr/share/applications/python3.7.desktop [Desktop Entry] Name=Python (v3.7) Comment=Python Interpreter (v3.7) Exec=/usr/bin/python3.7 Icon=/usr/share/pixmaps/python3.7.xpm Terminal=true Type=Application Categories=Development; StartupNotify=true NoDisplay=true wulfraed at debian:~$ wulfraed at debian:~$ cat /etc/mime.types ############################################################################### # # MIME media types and the extensions that represent them. # # The format of this file is a media type on the left and zero or more # filename extensions on the right. Programs using this file will map # files ending with those extensions to the associated type. # # This file is part of the "mime-support" package. Please report a bug using # the "reportbug" command of the "reportbug" package if you would like new # types or extensions to be added. # # The reason that all types are managed by the mime-support package instead # allowing individual packages to install types in much the same way as they # add entries in to the mailcap file is so these types can be referenced by # other programs (such as a web server) even if the specific support package # for that type is not installed. # # Users can add their own types if they wish by creating a ".mime.types" # file in their home directory. Definitions included there will take # precedence over those listed here. # ############################################################################### application/activemessage application/andrew-inset ez application/annodex anx application/applefile application/atom+xml atom ... application/x-python-code pyc pyo ... text/x-python py ... wulfraed at debian:~$ cat /usr/share/applications/gvim.desktop [Desktop Entry] Name=gVim GenericName=Text Editor ... TryExec=gvim Exec=gvim -f %F Terminal=false Type=Application Keywords=Text;editor; Icon=gvim Categories=Utility;TextEditor;Development; StartupNotify=true MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;text/x-python;text/x-python3 wulfraed at debian:~$ ALL of that is needed to link a Python source code file (.py) to GVIM editor, when clicked on from the desktop. >UNIX's execve() is able to read the first line of an executable and >invoke its interpreter. I guess OS/2 was doing precisely that in a >different way? > No... the UNIX/Linux shebang (and binary file equivalent magic-number) is a deliberately written part of a file's "data" content (granted, the linker writes it for executable binaries). The description for OS/2 is close to the little used Windows STREAMS feature. https://docs.microsoft.com/en-us/windows/win32/fileio/file-streams https://docs.microsoft.com/en-us/windows/win32/fileio/using-streams > >I cannot imagine. I always wondered what REXX was about --- I saw >programs sometimes written in some website whose name is something like >Rosetta Code. REXX looked so weird. (``Who would program in that?'') REXX was created by an IBM researcher who wanted something better than mainframe JCL (Job Control Language). https://en.wikipedia.org/wiki/Rexx >Yeah, REXX looks horrible at first. But arbitrary-precision is >definitely very attractive. I never liked to deal with floating-point. > Unfortunately, the most commonly available is Regina REXX, and to my knowledge it did not implement the arbitrary precision feature. Softrware emulation of multprecision floating point is slooooooooooooooooooowwww! -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From grant.b.edwards at gmail.com Thu Aug 12 16:23:22 2021 From: grant.b.edwards at gmail.com (Grant Edwards) Date: Thu, 12 Aug 2021 20:23:22 -0000 (UTC) Subject: some problems for an introductory python test References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86lf599zse.fsf@jevedi.xotimo> <868s18b1p7.fsf@jevedi.com> <868s16zol5.fsf@jevedi.com> <4c9de5d7-97ff-65b0-8669-8dc17f229fd0@mrabarnett.plus.com> Message-ID: On 2021-08-12, MRAB wrote: > >> Windows never had filesystems that supported metadata like OS/2 and >> MacOS did. The registry was an ugly hack that attempted (very poorly) >> to make up for that lack of metadata. >> > FYI, NTFS does support Alternate Data Streams. That is interesting -- and it was apparently intended to provide some sort of compatibility with MacOS data fork and resource fork. According to one article I found, nobody ever seems to have put that NTFS feature to use for anything other than hiding malware. -- Grant From wlfraed at ix.netcom.com Thu Aug 12 17:15:58 2021 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Thu, 12 Aug 2021 17:15:58 -0400 Subject: some problems for an introductory python test References: <86lf599zse.fsf@jevedi.xotimo> <868s18b1p7.fsf@jevedi.com> <868s16zol5.fsf@jevedi.com> Message-ID: On Fri, 13 Aug 2021 04:41:42 +1000, Chris Angelico declaimed the following: >Yeah. It was a strange choice by today's standards, but back then, >most of my GUI programs were written in REXX. > >https://en.wikipedia.org/wiki/VX-REXX >http://www.edm2.com/0206/vrexx.html > There was a library for the Amiga ARexx that supported basic GUI implementation too... >And of COURSE nobody would ever take an old serial mouse, take the >ball out of it, and turn it into a foot-controlled signal... although Of course not -- you'd want an old joyboard for that https://en.wikipedia.org/wiki/Joyboard > >SysRq should theoretically be that. (That's Alt+PrtSc on a lot of >keyboards.) I'm not sure how it could best be handled though. It might While so marked, Windows, at least, interprets as "grab image of current Window", whereas is "grab image of entire display". >be that today's GUI systems (X11, Wayland, Cocoa, Win32, etc) just >wouldn't work with a single input queue. Would be curious to see if >any modern OS/GUI pair has a synchronous input queue like that. > Not "modern" in this era, but I'm fairly certain the Amiga used a single stream queue. But that stream was fed to every application running, leaving it up to the application to determine if the event was something it had to handle, or pass on further. It was also fairly easy to inject events into the stream (which could help finding some of the easter eggs in the OS -- rather difficult to hold down , , , , AND, while holding them down, eject and insert a floppy disk. [without the floppy, to put up a credits display for the people who had worked on parts of the OS... The floppy mess then brought up a display with approximately "we created Amiga, CBM messed it up"]) -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From cs at cskk.id.au Thu Aug 12 19:42:20 2021 From: cs at cskk.id.au (Cameron Simpson) Date: Fri, 13 Aug 2021 09:42:20 +1000 Subject: some problems for an introductory python test In-Reply-To: <86mtpob2q2.fsf@jevedi.com> References: <86mtpob2q2.fsf@jevedi.com> Message-ID: On 11Aug2021 09:11, Hope Rouselle wrote: >Greg Ewing writes: >> That may not be doing what you think it's doing. Consider also >> >>>>> if0: print('yes!') >> yes! > >So, yes, that's puzzling. > >>>> 0 == False >True >>>> if0: print("yes") >yes >>>> if(0): print("yes") > >>>> > >What's going on there? 1: "if0" does not mean "if 0"; "if0" is a valid identifier. Like "x0", "x1". 2: It took me a while to see, but this is a type annotiation. This line: if0: print('yes!') says that the name "if0" should contain a value described by the return value of the expression "print('yes!')". Like this: label : str says that we expect a string in the variable "label". Remember that Python is strongly typed, but variables may reference objects of any type. Type annotations are optional things reflecting that in practice most variables are expected to reference specific types. This lets is run static linters against programmes to catch mistakes exposed by the type descriptions. Also, type annotations have _no_ runtime effect. So if that expression returns an invalid type description, nobody cares! However, if you hand this code to a type aware linter such as mypy you might get bitter complaints about nonsense. (Or, since print() returns None, no complaint - it just means you expect this variable to hold the value None. You'd get complaints about unused variables etc.) Cheers, Cameron Simpson From cs at cskk.id.au Thu Aug 12 20:12:12 2021 From: cs at cskk.id.au (Cameron Simpson) Date: Fri, 13 Aug 2021 10:12:12 +1000 Subject: some problems for an introductory python test In-Reply-To: <868s16zol5.fsf@jevedi.com> References: <868s16zol5.fsf@jevedi.com> Message-ID: On 12Aug2021 12:09, Hope Rouselle wrote: >Chris Angelico writes: >> [...] Plus, it had this fancy >> concept of "extended attributes"; on older systems (like MS-DOS's >> "FAT" family), a file might be Read-Only, Hidden, a System file, or >> needing to be Archived, and that was it - but on HPFS, you could >> attach arbitrary data like "File type: DeScribe Word Processor" or >> "Double click action: Run CASMake.cmd". This allowed the GUI to store >> all kinds of information *on the file itself* instead of needing >> hidden files (or, in Windows' case, the registry) to track that kind >> of thing. > >Yeah, that's kinda nice. Isn't that a UNIX design? A file is a >sequence of bytes? Users decide what to put in them? Yes, but extended attributes are outside the file data. They're very common on UNIX platforms these days. You can label arbitrary files with a file type or whatever else. (There are platform specific limitations, and even the OS API to deal with them is platform specific - Linux is different to FreeBSD is different to MacOS.) Also, Python has support for accessing these off-to-the-side data: https://docs.python.org/3/library/os.html#linux-extended-attributes Labelled "Linux" but also available for FreeBSD and IIRC OpenBSD. You do of course need filesystem support - FAT32 for example would not work with this - the filesystem needs a way to store these things. But ext4 and XFS on Linux, HFS+ on MacOS etc all support this. I've even got a CPython branch where I'm implementing the MacOS backend for these calls, a little stalled. Cheers, Cameron Simpson From greg.ewing at canterbury.ac.nz Thu Aug 12 21:24:34 2021 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Fri, 13 Aug 2021 13:24:34 +1200 Subject: some problems for an introductory python test In-Reply-To: References: <86mtpob2q2.fsf@jevedi.com> Message-ID: On 13/08/21 11:42 am, Cameron Simpson wrote: > 2: It took me a while to see, but this is a type annotiation. Interestingly, it seems to be parsed as a form of assignment with a missing RHS. >>> from ast import parse, dump >>> dump(parse("if0: print('yes!')")) "Module(body=[AnnAssign(target=Name(id='if0', ctx=Store()), annotation=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='yes!', kind=None)], keywords=[]), value=None, simple=1)], type_ignores=[])" "An annotated assignment without the assignment? Eeuurgh!" -- Greg From greg.ewing at canterbury.ac.nz Thu Aug 12 21:28:18 2021 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Fri, 13 Aug 2021 13:28:18 +1200 Subject: some problems for an introductory python test In-Reply-To: References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86lf599zse.fsf@jevedi.xotimo> <868s18b1p7.fsf@jevedi.com> <868s16zol5.fsf@jevedi.com> Message-ID: On 13/08/21 5:52 am, Grant Edwards wrote: > I think what he's talking about is allowing the user to attach > arbitrary _metadata_ to the file ... IOW, something similar to the > "resource fork" that MacOS used to have. The resource fork was used for more than just metadata, it was often the entire contents of the file. Applications had all the code in there, for example -- the data fork of an application was usually empty. -- Greg From riditagarwal11 at gmail.com Fri Aug 13 00:49:36 2021 From: riditagarwal11 at gmail.com (Ridit) Date: Fri, 13 Aug 2021 10:19:36 +0530 Subject: pip doesn't work Message-ID: <7BABCE48-779A-40BB-A030-BF778221429E@hxcore.ol> So, whoever gets this, when I try to download packages using pip, it shows errors saying "'pip' is not recognized as an internal or external command, operable program or batch file." Is there a way to solve this? I tried modifying, even repairing three times, but still it doesn't work. If you have a solution, thank you. From __peter__ at web.de Fri Aug 13 02:00:31 2021 From: __peter__ at web.de (Peter Otten) Date: Fri, 13 Aug 2021 08:00:31 +0200 Subject: pip doesn't work In-Reply-To: <7BABCE48-779A-40BB-A030-BF778221429E@hxcore.ol> References: <7BABCE48-779A-40BB-A030-BF778221429E@hxcore.ol> Message-ID: On 13/08/2021 06:49, Ridit wrote: > So, whoever gets this, when I try to download packages using pip, it shows > errors saying "'pip' is not recognized as an internal or external command, > operable program or batch file." Is there a way to solve this? I tried > modifying, even repairing three times, but still it doesn't work. If you > have a solution, thank you. Try invoking it with py -m pip ... instead of just pip ... From tjreedy at udel.edu Fri Aug 13 11:46:30 2021 From: tjreedy at udel.edu (Terry Reedy) Date: Fri, 13 Aug 2021 11:46:30 -0400 Subject: Regarding inability of Python Module Winsound to produce beep in decimal frequency In-Reply-To: References: Message-ID: On 8/13/2021 6:53 AM, Umang Goswami wrote: > Hi There, Hope you find this mail in good health. > > I am Umang Goswami, a Python developer and student working on a huge > project for automation of music instruments. I am producing the musical > notes using the Beep function of Winsound Module( > https://docs.python.org/3/library/winsound.html) by passing frequency as a > argument to the function. > > Now whenever i provide frequency of any note in decimal(for example > 277.1826 for C4 note) it shows following error: > Traceback (most recent call last): > File "C:\Users\Umang Goswami\Desktop\Umang Goswami\test.py", line 2, in > > winsound.Beep(111.11,111111) > TypeError: integer argument expected, got float > > Now I have to round up the frequencies. This is hurting the quality, > accuracy ,authenticity and future of the project. Almost all the notes have > the frequencies in decimal parts. Rounding up means changing semitones and > quatertones thus whole note itself. This problem is technically making my > program useless. > > Its my humble request to you all, I beg you, Please tell me how to overcome > this issue. I have consulted many sources both online and offline but I > remained unsatisfied. I can not make audio files of each note because there > are many many notes and so practically making so many files of different > time length wont help. > > Please suggest to me the way to resolve this issue or is there any other > module to produce the sound of decimal frequency. Without knowing what sources you have already looked at, anything anyone might say might be duplication. However,... If the builtin hardware sound generator only generates integral frequencies, you are stuck unless you get an add-in card that is more flexible. If the Windows interface to the hardware only accepts integral frequencies, which I suspect might be true, ditto, unless you get custom software. You could look at pygame and see what its sound functions do. And search pypi for 'sound generator' or 'frequency generator'. -- Terry Jan Reedy From rosuav at gmail.com Fri Aug 13 12:17:05 2021 From: rosuav at gmail.com (Chris Angelico) Date: Sat, 14 Aug 2021 02:17:05 +1000 Subject: Regarding inability of Python Module Winsound to produce beep in decimal frequency In-Reply-To: References: Message-ID: On Sat, Aug 14, 2021 at 2:11 AM Terry Reedy wrote: > > On 8/13/2021 6:53 AM, Umang Goswami wrote: > > Hi There, Hope you find this mail in good health. > > > > I am Umang Goswami, a Python developer and student working on a huge > > project for automation of music instruments. I am producing the musical > > notes using the Beep function of Winsound Module( > > https://docs.python.org/3/library/winsound.html) by passing frequency as a > > argument to the function. > > > > Now whenever i provide frequency of any note in decimal(for example > > 277.1826 for C4 note) it shows following error: > > Traceback (most recent call last): > > File "C:\Users\Umang Goswami\Desktop\Umang Goswami\test.py", line 2, in > > > > winsound.Beep(111.11,111111) > > TypeError: integer argument expected, got float > > > > Now I have to round up the frequencies. This is hurting the quality, > > accuracy ,authenticity and future of the project. Almost all the notes have > > the frequencies in decimal parts. Rounding up means changing semitones and > > quatertones thus whole note itself. This problem is technically making my > > program useless. > > Is it really? In my experience, no human ear can distinguish 277Hz from 277.1826Hz when it's played on a one-bit PC speaker, which the Beep function will be using. ChrisA From python at mrabarnett.plus.com Fri Aug 13 12:41:05 2021 From: python at mrabarnett.plus.com (MRAB) Date: Fri, 13 Aug 2021 17:41:05 +0100 Subject: Regarding inability of Python Module Winsound to produce beep in decimal frequency In-Reply-To: References: Message-ID: <396db396-272b-b7a4-2daf-92e26d005535@mrabarnett.plus.com> On 2021-08-13 17:17, Chris Angelico wrote: > On Sat, Aug 14, 2021 at 2:11 AM Terry Reedy wrote: >> >> On 8/13/2021 6:53 AM, Umang Goswami wrote: >> > Hi There, Hope you find this mail in good health. >> > >> > I am Umang Goswami, a Python developer and student working on a huge >> > project for automation of music instruments. I am producing the musical >> > notes using the Beep function of Winsound Module( >> > https://docs.python.org/3/library/winsound.html) by passing frequency as a >> > argument to the function. >> > >> > Now whenever i provide frequency of any note in decimal(for example >> > 277.1826 for C4 note) it shows following error: >> > Traceback (most recent call last): >> > File "C:\Users\Umang Goswami\Desktop\Umang Goswami\test.py", line 2, in >> > >> > winsound.Beep(111.11,111111) >> > TypeError: integer argument expected, got float >> > >> > Now I have to round up the frequencies. This is hurting the quality, >> > accuracy ,authenticity and future of the project. Almost all the notes have >> > the frequencies in decimal parts. Rounding up means changing semitones and >> > quatertones thus whole note itself. This problem is technically making my >> > program useless. >> > > > Is it really? In my experience, no human ear can distinguish 277Hz > from 277.1826Hz when it's played on a one-bit PC speaker, which the > Beep function will be using. > I've just tried it on my PC and I couldn't hear the difference, except that odd frequencies had a momentary break in them during longer notes whereas even frequencies didn't. Very odd... From coduibhin at btinternet.com Fri Aug 13 14:32:51 2021 From: coduibhin at btinternet.com (=?utf-8?q?Ciar=c3=a1n=20=c3=93=20Duibh=c3=adn?=) Date: Fri, 13 Aug 2021 18:32:51 +0000 Subject: Can't get rid of old version of python Message-ID: Hi, On Windows 10, I uninstalled all previous versions of Python and installed v3.9.6. When I use the start menu option Python 3.9 (64-bit), I get the prompt "Python 3.9.6" as expected. The same happens when I type "py" at the DOS prompt. But when I type "python" at the DOS prompt, I get "Python 3.8.10". I don't understand this, as I uninstalled old versions, and I do not see a DOS environment variable called "python" anywhere. The real problem comes when I install a package, e.g. germalemma. Python 3.8.10 can use it, but Python 3.9.6 can't find it. I notice that "site-packages" containing germalemma and its dependencies is located in ...Packages\PythonSoftwareFoundationPython.3.8.qbz5n2kfra8p0\LocalCache\local-packages\Python3.8 Also there is a load of python 3.8 stuff at C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.8_3.8.2800.0_x64__qbz5n2kfra8p0 which directory is virtually inaccessible from Windows but can be listed in DOS. How can I get rid of Python 3.8.10 , and install my packages to 3.9.6? Ciar?n ? Duibh?n From wlfraed at ix.netcom.com Fri Aug 13 15:42:43 2021 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Fri, 13 Aug 2021 15:42:43 -0400 Subject: pip doesn't work References: <7BABCE48-779A-40BB-A030-BF778221429E@hxcore.ol> Message-ID: On Fri, 13 Aug 2021 10:19:36 +0530, Ridit declaimed the following: > So, whoever gets this, when I try to download packages using pip, it shows > errors saying "'pip' is not recognized as an internal or external command, > operable program or batch file." Is there a way to solve this? I tried > modifying, even repairing three times, but still it doesn't work. If you > have a solution, thank you. If you really want PIP as a stand-alone executable, you need to add its location to the system PATH environment variable. {Which will also make everything else in /Scripts available to the command line. Alternatively, you invoke Python passing it a "-m pip " (without the ") -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From michael.stemper at gmail.com Fri Aug 13 16:11:58 2021 From: michael.stemper at gmail.com (Michael F. Stemper) Date: Fri, 13 Aug 2021 15:11:58 -0500 Subject: on slices, negative indices, which are the equivalent procedures? In-Reply-To: References: <86sfznhk1f.fsf@example.com> <86wnos9ge8.fsf@jevedi.com> <4vi8hg1tfcd2vsrchgpnbpf9a9l7acf7rl@4ax.com> Message-ID: On 11/08/2021 20.17, dn wrote: > > I've been trying to remember if we had negative-steps in FORTRAN > do-loops My text for Fortran 77 (the last version that I ever used) says that negative increments are supported. Ref: _FORTRAN 77: Language and Style_; Michael J. Merchant; Wadsworth Publishing Company; (c) 1981; Page 125 It also says that zero increments are not supported. (Whew!) -- Michael F. Stemper 87.3% of all statistics are made up by the person giving them. From wlfraed at ix.netcom.com Fri Aug 13 16:31:03 2021 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Fri, 13 Aug 2021 16:31:03 -0400 Subject: Can't get rid of old version of python References: Message-ID: On Fri, 13 Aug 2021 18:32:51 +0000, Ciar?n ? Duibh?n via Python-list declaimed the following: > >Also there is a load of python 3.8 stuff at C:\Program >Files\WindowsApps\PythonSoftwareFoundation.Python.3.8_3.8.2800.0_x64__qbz5n2kfra8p0 >which directory is virtually inaccessible from Windows but can be listed >in DOS. > >How can I get rid of Python 3.8.10 , and install my packages to 3.9.6? > You probably can't... The keyword being "WindowApps". That version likely was installed using the Win10 "app store" (aka: "microsoft store"). You can open that, click the ... and pick "my library", pick "installed" and likely find a Python entry. But the appstore does not allow one to delete downloaded apps! It MIGHT be removable if you locate a "Python" icon on the start-menu and right click "uninstall" -- but make sure it is not YOUR Python... The simplest method would be to ensure YOUR Python is at the top of the PATH environment variable so it is found first when searching for applications. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From tjreedy at udel.edu Fri Aug 13 17:57:17 2021 From: tjreedy at udel.edu (Terry Reedy) Date: Fri, 13 Aug 2021 17:57:17 -0400 Subject: Can't get rid of old version of python In-Reply-To: References: Message-ID: On 8/13/2021 2:32 PM, Ciar?n ? Duibh?n via Python-list wrote: > Hi, > > On Windows 10, I uninstalled all previous versions of Python and > installed v3.9.6. > > When I use the start menu option Python 3.9 (64-bit), I get the prompt > "Python 3.9.6" as expected.? The same happens when I type "py" at the > DOS prompt. > > But when I type "python" at the DOS prompt, I get "Python 3.8.10".? I > don't understand this, as I uninstalled old versions, and I do not see a > DOS environment variable called "python" anywhere. > > The real problem comes when I install a package, e.g. germalemma. Python > 3.8.10 can use it, but Python 3.9.6 can't find it. If 'py' starts 3.9, then py -m pip install xyz will install xyz for 3.9. (In not, py -3.9 -m pip ... will) The command 'python' takes one to the MS store unless one has already gotten the store python. -- Terry Jan Reedy From eryksun at gmail.com Fri Aug 13 18:48:43 2021 From: eryksun at gmail.com (Eryk Sun) Date: Fri, 13 Aug 2021 17:48:43 -0500 Subject: Can't get rid of old version of python In-Reply-To: References: Message-ID: On 8/13/21, Ciar?n ? Duibh?n via Python-list wrote: > > But when I type "python" at the DOS prompt, I get "Python 3.8.10". I > don't understand this, as I uninstalled old versions, and I do not see a > DOS environment variable called "python" anywhere. The app distribution is probably installed. You can uninstall it in the "Apps" view of the settings apps. The app should be named "Python 3.8" from "Python Software Foundation". Alternatively, if you want to keep the app distribution, you can simply remove interfering aliases. Towards the top, there's a link to set "App execution aliases". You can disable all of the Python-related aliases, or keep specific aliases such as "python3.8.exe", "pythonw3.8.exe", "pip3.8.exe", and "idle3.8.exe". --- FYI, back in the 1990s, when users opened a "DOS Box" in Windows 9x, it was literally the 16-bit DOS kernel and "COMMAND.COM" shell executing in a virtual DOS machine (VDM) using the CPU's virtual-86 mode. Various software interrupts were hooked to integrate with the virtual machine manager (the 32-bit OS at the core of Windows 9x) and connect the UI to a desktop window. The term "DOS Box" made perfect sense back then. In modern Windows systems, which are based on NT instead of DOS, the classic command-line shell is called the "Command Prompt" or "CMD". The CMD shell (cmd.exe) is a Windows console application. It supports the batch language and a superset of the commands from the "COMMAND.COM" DOS shell. Compatibility with the DOS shell was crucial when CMD was designed for OS/2 in 1986 and subsequently ported to Windows in 1993. But it's only high-level and superficial compatibility. CMD directly consumes the Windows API. It is not a DOS application executing in a VDM. 64-bit Windows systems don't even include VDM support. From coduibhin at btinternet.com Fri Aug 13 19:11:01 2021 From: coduibhin at btinternet.com (=?utf-8?q?Ciar=c3=a1n=20=c3=93=20Duibh=c3=adn?=) Date: Fri, 13 Aug 2021 23:11:01 +0000 Subject: Can't get rid of old version of python In-Reply-To: References: Message-ID: Many thanks for both replies. Everything seems fine now. Reinstalling the packages using "py" made them available in v3.9.6. So I could delete them from C:\Users\...\AppData\Local\Packages\PythonSoftwareFoundationPython.3.8.qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages In fact I deleted the whole of C:\Users\...\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8.qbz5n2kfra8p0 Asking where "python" finds its (supposed uninstalled) v3.8.10 executable was sending me to 'C:\Users\?\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\python.exe' but deleting as above meant there is no longer a "python" command to worry about. I may try to remove that whole subdirectory of WindowsApps and the somewhat similar one in C:\Program Files\WindowsApps I think any other applications that use python probably have their own copy of python.exe ? LibreOffice and GIMP 2 certainly have, with version numbers which are different again. From johndavidgriner74 at gmail.com Fri Aug 13 18:33:22 2021 From: johndavidgriner74 at gmail.com (John Griner) Date: Fri, 13 Aug 2021 18:33:22 -0400 Subject: Recoding Categorical to Numerical Message-ID: Hello, and thanks in advance, I am trying to recode categorical variable to numeric. Despite using lambda, If else, dummy-recoding, and so forth, what I get is from ONE column that has 4 variables (City, Town, Suburb, Rural), I get FOUR columns: localeDummy_City localeDummy_Town localeDummy_Suburb localeDummy_Rural locale_recode with the corresponding numeric variable. What I want is the recode to have ONE column that has the numeric conversion. For instance: local_recode 2 4 4 6 2 8 6 2 8 2 2 4 6 4 8 and so forth, where I have set City to 2, and Town to 4, etc. Again, thanks, John loca Virus-free. www.avast.com <#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2> From guruyaya at gmail.com Fri Aug 13 18:44:20 2021 From: guruyaya at gmail.com (guruyaya) Date: Fri, 13 Aug 2021 15:44:20 -0700 (PDT) Subject: Empty list as a default param - the problem, and my suggested solution Message-ID: I am fairly sure all of us know about this python quirk: >>> def no_new_func(a=[]): ... a.append('new') ... return a >>> no_new_func() ['new'] >>> no_new_func() ['new', 'new'] >>> For some time I was bothered about that there's no elegant way to use empty list or dict as a default parameter. While this can be solved like this: >>> def no_new_func(a=None): ... if a == None: a = [] ... a.append('new') ... return a I have to say I find this solution very far from the spirit of python. Kinda ugly, and not explicit. So I've decided to try and create a new module, that will try and make, what I think, is a more beautiful and explicit: >>> from new import NEW >>> @NEW.parse ... def new_func(a=NEW.new([])): ... a.append('new appended') ... return a ... >>> new_func() ['new appended'] >>> new_func() ['new appended'] I'd like to hear your thoughts on my solution and code. You can find and give your feedback in this project https://github.com/guruyaya/new If I see that people like this, I will upload it to pip. I'm not fully sure about the name I choose (I thought about the "new" keyword used in JAVA, not sure it applies here as well) Thanks in advance for your feedback Yair From coduibhin at btinternet.com Fri Aug 13 19:34:24 2021 From: coduibhin at btinternet.com (=?utf-8?q?Ciar=c3=a1n=20=c3=93=20Duibh=c3=adn?=) Date: Fri, 13 Aug 2021 23:34:24 +0000 Subject: Can't get rid of old version of python In-Reply-To: References: Message-ID: Thanks for the two further clarifications, which I've just read. Eryk's advice for uninstalling the app distribution got rid of those unwanted WindowsApps subdirectories painlessly. From __peter__ at web.de Sat Aug 14 04:31:34 2021 From: __peter__ at web.de (Peter Otten) Date: Sat, 14 Aug 2021 10:31:34 +0200 Subject: Recoding Categorical to Numerical In-Reply-To: References: Message-ID: On 14/08/2021 00:33, John Griner wrote: > Hello, and thanks in advance, > > I am trying to recode categorical variable to numeric. Despite using > lambda, If else, dummy-recoding, and so forth, what I get is from ONE > column that has 4 variables (City, Town, Suburb, Rural), I get FOUR columns: > > > > localeDummy_City localeDummy_Town localeDummy_Suburb > localeDummy_Rural locale_recode > > > > with the corresponding numeric variable. > > > > What I want is the recode to have ONE column that has the numeric > conversion. > > > > For instance: > > > local_recode > > 2 > > 4 > > 4 > > 6 > > 2 > > 8 > > 6 > > 2 > > 8 > > 2 > > 2 > > 4 > > 6 > > 4 > > 8 > > and so forth, where I have set City to 2, and Town to 4, etc. > > > Again, thanks, John My crystal ball says you want import pandas df = pandas.DataFrame( [ [("City", "Suburb")], [("Town", "City", "Suburb")], [("Rural",)] ], columns=["before"] ) flags = dict( City=1, Town=2, Suburb=4, Rural=8 ) df["after"] = df["before"].apply( lambda names: sum(flags[name] for name in set(names)) ) print(df) If that's not it show us your failing code, preferably as a small self-contained script that also generates the required input data. Use cut and paste, and include it into the message body as attachments are usually removed. From martinp.dipaola at gmail.com Sat Aug 14 19:40:07 2021 From: martinp.dipaola at gmail.com (Martin Di Paola) Date: Sat, 14 Aug 2021 23:40:07 +0000 Subject: Empty list as a default param - the problem, and my suggested solution In-Reply-To: References: Message-ID: <20210814234007.hgyfnufwvhzonn47@gmail.com> I don't know if it is useful but it is an interesting metaprogramming/reflection challenge. You used `inspect` but you didn't take its full potential. Try to see if you can simplify your code and see if you can come with a decorator that does not require special parameters. >>> from new import NEW >>> @NEW ... def new_func(a=[]): ... a.append('new appended') ... return a ... >>> new_func() ['new appended'] >>> new_func() ['new appended'] Spoiler - My solution is at https://book-of-gehn.github.io/articles/2021/08/14/Fresh-Python-Defaults.html On Fri, Aug 13, 2021 at 03:44:20PM -0700, guruyaya wrote: >I am fairly sure all of us know about this python quirk: >>>> def no_new_func(a=[]): >... a.append('new') >... return a > >>>> no_new_func() >['new'] >>>> no_new_func() >['new', 'new'] >>>> > >For some time I was bothered about that there's no elegant way to use empty list or dict as a default parameter. While this can be solved like this: >>>> def no_new_func(a=None): >... if a == None: > a = [] >... a.append('new') >... return a > >I have to say I find this solution very far from the spirit of python. Kinda ugly, and not explicit. So I've decided to try and create a new module, that will try and make, what I think, is a more beautiful and explicit: > >>>> from new import NEW >>>> @NEW.parse >... def new_func(a=NEW.new([])): >... a.append('new appended') >... return a >... >>>> new_func() >['new appended'] >>>> new_func() >['new appended'] > >I'd like to hear your thoughts on my solution and code. You can find and give your feedback in this project >https://github.com/guruyaya/new >If I see that people like this, I will upload it to pip. I'm not fully sure about the name I choose (I thought about the "new" keyword used in JAVA, not sure it applies here as well) > >Thanks in advance for your feedback >Yair >-- >https://mail.python.org/mailman/listinfo/python-list From research at johnohagan.com Sat Aug 14 23:01:17 2021 From: research at johnohagan.com (John O'Hagan) Date: Sun, 15 Aug 2021 13:01:17 +1000 Subject: Regarding inability of Python Module Winsound to produce beep in decimal frequency In-Reply-To: <396db396-272b-b7a4-2daf-92e26d005535@mrabarnett.plus.com> References: <396db396-272b-b7a4-2daf-92e26d005535@mrabarnett.plus.com> Message-ID: <20210815130117.03c23726@e7240.home> On Fri, 13 Aug 2021 17:41:05 +0100 MRAB wrote: > On 2021-08-13 17:17, Chris Angelico wrote: > > On Sat, Aug 14, 2021 at 2:11 AM Terry Reedy > > wrote: > >> > >> On 8/13/2021 6:53 AM, Umang Goswami wrote: > >> > Hi There, Hope you find this mail in good health. > >> > > >> > I am Umang Goswami, a Python developer and student working on a > >> > huge project for automation of music instruments. I am producing > >> > the musical notes using the Beep function of Winsound Module( > >> > https://docs.python.org/3/library/winsound.html) by passing > >> > frequency as a argument to the function. > >> > > >> > Now whenever i provide frequency of any note in decimal(for > >> > example 277.1826 for C4 note) it shows following error: > >> > Traceback (most recent call last): > >> > File "C:\Users\Umang Goswami\Desktop\Umang Goswami\test.py", > >> > line 2, in > >> > winsound.Beep(111.11,111111) > >> > TypeError: integer argument expected, got float > >> > > >> > Now I have to round up the frequencies. This is hurting the > >> > quality, accuracy ,authenticity and future of the project. > >> > Almost all the notes have the frequencies in decimal parts. > >> > Rounding up means changing semitones and quatertones thus whole > >> > note itself. This problem is technically making my program > >> > useless. > >> > > > > > Is it really? In my experience, no human ear can distinguish 277Hz > > from 277.1826Hz when it's played on a one-bit PC speaker, which the > > Beep function will be using. > > > I've just tried it on my PC and I couldn't hear the difference, > except that odd frequencies had a momentary break in them during > longer notes whereas even frequencies didn't. Very odd... Rounding to integer frequencies will produce disastrously out-of-tune notes in a musical context! Particularly for low notes, where a whole semitone is only a couple of Hz difference. Even for higher notes, when they're played together any inaccuracies are much more apparent. To the OP, there aren't too many options in pure python for playing audio - to do anything complicated I've used applications such as Fluidsynth and sox as python subprocesses. But for playing purely generated tones, here's an example that doesn't limit frequency precision, using pyaudio to play a numpy array representing a sine-wave: import pyaudio, numpy as np f = 555.555 #frequency d = 1.0 # duration in seconds rate = 44100 #sample rate p = pyaudio.PyAudio() stream = p.open(format=pyaudio.paFloat32, channels=1, rate=rate, output=True) samples = np.sin(2*np.pi*np.arange(rate*d)*f/rate).astype(np.float32) stream.write(samples) Hope this helps John From rosuav at gmail.com Sun Aug 15 01:01:51 2021 From: rosuav at gmail.com (Chris Angelico) Date: Sun, 15 Aug 2021 15:01:51 +1000 Subject: Regarding inability of Python Module Winsound to produce beep in decimal frequency In-Reply-To: <20210815130117.03c23726@e7240.home> References: <396db396-272b-b7a4-2daf-92e26d005535@mrabarnett.plus.com> <20210815130117.03c23726@e7240.home> Message-ID: On Sun, Aug 15, 2021 at 1:02 PM John O'Hagan wrote: > > > On 2021-08-13 17:17, Chris Angelico wrote: > > > Is it really? In my experience, no human ear can distinguish 277Hz > > > from 277.1826Hz when it's played on a one-bit PC speaker, which the > > > Beep function will be using. > > Rounding to integer frequencies will produce disastrously out-of-tune > notes in a musical context! Particularly for low notes, where a whole > semitone is only a couple of Hz difference. Even for higher notes, when > they're played together any inaccuracies are much more apparent. But before you advocate that too hard, check to see the *real* capabilities of a one-bit PC speaker. You go on to give an example that uses PyAudio and a sine wave, not the timer chip's "beep" functionality. Try getting some recordings of a half dozen or so computers making a beep at 440Hz. Then do some analysis on the recordings and see whether they're actually within 1Hz of that. (And that's aside from the fact that quite a number of computers will show up completely silent, due to either not having an internal speaker, or not letting you use it.) ChrisA From joel.goldstick at gmail.com Sun Aug 15 03:19:33 2021 From: joel.goldstick at gmail.com (Joel Goldstick) Date: Sun, 15 Aug 2021 03:19:33 -0400 Subject: Regarding inability of Python Module Winsound to produce beep in decimal frequency In-Reply-To: References: <396db396-272b-b7a4-2daf-92e26d005535@mrabarnett.plus.com> <20210815130117.03c23726@e7240.home> Message-ID: On Sun, Aug 15, 2021 at 1:03 AM Chris Angelico wrote: > > On Sun, Aug 15, 2021 at 1:02 PM John O'Hagan wrote: > > > > > On 2021-08-13 17:17, Chris Angelico wrote: > > > > Is it really? In my experience, no human ear can distinguish 277Hz > > > > from 277.1826Hz when it's played on a one-bit PC speaker, which the > > > > Beep function will be using. > > > > Rounding to integer frequencies will produce disastrously out-of-tune > > notes in a musical context! Particularly for low notes, where a whole > > semitone is only a couple of Hz difference. Even for higher notes, when > > they're played together any inaccuracies are much more apparent. > > But before you advocate that too hard, check to see the *real* > capabilities of a one-bit PC speaker. You go on to give an example > that uses PyAudio and a sine wave, not the timer chip's "beep" > functionality. > > Try getting some recordings of a half dozen or so computers making a > beep at 440Hz. Then do some analysis on the recordings and see whether > they're actually within 1Hz of that. > > (And that's aside from the fact that quite a number of computers will > show up completely silent, due to either not having an internal > speaker, or not letting you use it.) > > ChrisA > -- > https://mail.python.org/mailman/listinfo/python-list This thread got me curious, and I found this article. The code is very similar to the pyaudio version a few responses back. https://thehackerdiary.wordpress.com/2017/06/09/it-is-ridiculously-easy-to-generate-any-audio-signal-using-python/ except it doesn't need pyaudio I run Ubuntu 20.04, and I had problems getting pyaudio on my machine. -- Joel Goldstick From roel at roelschroeven.net Mon Aug 16 03:49:05 2021 From: roel at roelschroeven.net (Roel Schroeven) Date: Mon, 16 Aug 2021 09:49:05 +0200 Subject: Regarding inability of Python Module Winsound to produce beep in decimal frequency In-Reply-To: References: <396db396-272b-b7a4-2daf-92e26d005535@mrabarnett.plus.com> <20210815130117.03c23726@e7240.home> Message-ID: <6068cc72-6377-458d-0bde-35919f327782@roelschroeven.net> Op 15/08/2021 om 7:01 schreef Chris Angelico: > On Sun, Aug 15, 2021 at 1:02 PM John O'Hagan wrote: > > > > > On 2021-08-13 17:17, Chris Angelico wrote: > > > > Is it really? In my experience, no human ear can distinguish 277Hz > > > > from 277.1826Hz when it's played on a one-bit PC speaker, which the > > > > Beep function will be using. > > > > Rounding to integer frequencies will produce disastrously out-of-tune > > notes in a musical context! Particularly for low notes, where a whole > > semitone is only a couple of Hz difference. Even for higher notes, when > > they're played together any inaccuracies are much more apparent. > > But before you advocate that too hard, check to see the *real* > capabilities of a one-bit PC speaker. We're not necessarily talking about the PC speaker here: (almost) all computers these days have sound cards (mostly integrated on the motherboard) that are much more capable than those one-bit PC speakers. Beep uses that sound card, when available. I don't know how accurate the generated sound is though. -- "Now, the invention of the scientific method and science is, I'm sure we'll all agree, the most powerful intellectual idea, the most powerful framework for thinking and investigating and understanding and challenging the world around us that there is, and that it rests on the premise that any idea is there to be attacked and if it withstands the attack then it lives to fight another day and if it doesn't withstand the attack then down it goes. Religion doesn't seem to work like that; it has certain ideas at the heart of it which we call sacred or holy or whatever. That's an idea we're so familiar with, whether we subscribe to it or not, that it's kind of odd to think what it actually means, because really what it means is 'Here is an idea or a notion that you're not allowed to say anything bad about; you're just not. Why not? - because you're not!" -- Douglas Adams From drsalists at gmail.com Mon Aug 16 11:13:47 2021 From: drsalists at gmail.com (Dan Stromberg) Date: Mon, 16 Aug 2021 08:13:47 -0700 Subject: Cyclic imports Message-ID: Hi folks. I'm working on a large codebase that has at least one cyclic import. In case I end up needing to eliminate the cyclic imports, is there any sort of tool that will generate an import graph and output Just the cycles? I tried pyreverse, but it produced too big a graph to be very useful; it showed all internal imports, not just the cycles. Thanks! From jbrandom at example.com Sat Aug 14 23:05:29 2021 From: jbrandom at example.com (Jack Brandom) Date: Sun, 15 Aug 2021 00:05:29 -0300 Subject: on slices, negative indices, which are the equivalent procedures? References: <86sfznhk1f.fsf@example.com> <86wnos9ge8.fsf@jevedi.com> <4vi8hg1tfcd2vsrchgpnbpf9a9l7acf7rl@4ax.com> Message-ID: <86a6lj1k7a.fsf@jevedi.com> Dennis Lee Bieber writes: > On Wed, 11 Aug 2021 11:59:11 -0300, Jack Brandom > declaimed the following: > >> >>Where are these production rules coming from? They're not at >> >> https://docs.python.org/3/reference/grammar.html >> >>The word ``stride'' doesn't appear in this grammar. > > Possibly from older versions of the grammar, before simplification to > just . Originally, the "stride" term was added in response to > requests from the numerical library developers (NumPy seems to be the > survivor of that cluster). At the time, it wasn't envisioned to be usable > with regular Python objects. > > https://en.wikipedia.org/wiki/Array_slicing#1991:_Python > """ > The stride syntax (nums[1:5:2]) was introduced in the second half of the > 1990s, as a result of requests put forward by scientific users in the > Python "matrix-SIG" (special interest group). > """ Always great to know the history with good references. Thanks very much. > As for the grammar... Would you prefer that from 2.7? > > trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME > subscriptlist: subscript (',' subscript)* [','] > subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] > sliceop: ':' [test] > > test: or_test ['if' or_test 'else' test] | lambdef > or_test: and_test ('or' and_test)* > and_test: not_test ('and' not_test)* > not_test: 'not' not_test | comparison This is looking less readable, so, no, I prefer that previous, which was much clearer about slices. I can't even quite make the slices out in these rules. (But thanks for the opportunity to try.) From hrouselle at jevedi.com Sat Aug 14 23:15:58 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Sun, 15 Aug 2021 00:15:58 -0300 Subject: some problems for an introductory python test References: <86lf599zse.fsf@jevedi.xotimo> <868s18b1p7.fsf@jevedi.com> Message-ID: <86o89zz9ch.fsf@jevedi.com> Dennis Lee Bieber writes: > On Thu, 12 Aug 2021 06:15:28 +1000, Chris Angelico > declaimed the following: > >>The default command interpreter and shell on OS/2 was fairly primitive >>by today's standards, and was highly compatible with the MS-DOS one, >>but it also had the ability to run REXX scripts. REXX was *way* ahead >>of its time. It's a shell language but remarkably well suited to >>building GUIs and other tools (seriously, can you imagine designing a >>GUI entirely in a bash script??). It had features that we'd consider >>fairly normal or even primitive by Python's standards, but back then, >>Python was extremely new and didn't really have very much mindshare. >>REXX offered arbitrary-precision arithmetic, good databasing support, >>a solid C API that made it easy to extend, integrations with a variety >>of other systems... this was good stuff for its day. (REXX is still >>around, but these days, I'd rather use Python.) >> > I was spoiled by the Amiga variant of REXX. Most current > implementations (well, Regina is the only one I've looked at) can just pass > command to the default shell. The Amiga version took advantage of Intuition > Message Ports (OS supported IPC). That allowed it to "address > " any application that defined an ARexx port, allowing ARexx > to be used as a scripting language for that application (and with multiple > applications, one could easily fetch data from app1 and feed it to app2). > ARexx did not, to my memory, implement arbitrary precision math. > > Any statement in a REXX script that was not parsable as REXX would be > passed on the currently "addressed" command host. > > Granted, the fact that the Amiga used a shared common address space for > all running applications made IPC quite easy -- one looked up the > application message port, then added a small packet to the linked list > associated with the port. That small packet basically held the address of > the message port for returning data, and the address of the data being > passed. The closet thing I've seen to that capability on systems with > process-isolated virtual memory is (Open)VMS "mailbox" structures. The > difference being that the entire data had to be written (QIO) to the > mailbox, and the receiver had to read (another QIO call) the message -- > this allowed the address space to change. > > I've not seen anything equivalent in my light perusal of the Win32 API > (the various guide books aren't layed out in any way to be a reference), > and Linux seems to use UNIX sockets for IPC... No way to search for a > connection point by name... I don't know anything about Amiga, REXX et cetera, so I might be totall off here. But since you spoke of your perusal of the Win32 API, let me add a tiny bit. I gave myself a quick tour through the Win32 API using Pavel Yosifovich's book ``Windows 10 System Programming''. It's a two volume work. The thing that impressed me the most was the many ways to do the IPC. The purpose the work is clearly to show what is available and it it probably does the job well. (I ignored Windows for most of my life and now I decided to take a look at it. I don't feel it has much of the elegance of UNIX. It's what it is.) From hrouselle at jevedi.com Sat Aug 14 23:35:55 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Sun, 15 Aug 2021 00:35:55 -0300 Subject: some problems for an introductory python test References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86sfzha1ac.fsf@jevedi.xotimo> <86czqkb1z9.fsf@jevedi.com> Message-ID: <865yw7z8f8.fsf@jevedi.com> Dennis Lee Bieber writes: > On Wed, 11 Aug 2021 09:27:38 -0300, Hope Rouselle > declaimed the following: >> >>I wouldn't. This is all Python-stuff. The course chooses a language >>like Python, but it is not trying to teach Python --- it is trying to >>teach computer programming, that is, strategies in high-precision. > > Then I would posit you are teaching the wrong level... What you > describe is what would be found a "data structures" and/or "algorithms" > course -- which is a second year, if not third year course in my (ancient) > history. [...] Slicing with a stride isn't really useful to most > algorithm development -- it's more of trick in normal Python. I didn't express myself very well. And it's hard to make sense of the course. I say it's interested in teaching computer programming because it is not allowing the students to dive into the Python language. It's very restrictive. Students will finish the course after learning to use the loop contructs while and for. The course calls them ``structures for repetition''. I think it's safe to say that the course is designed by people concerned with education, but not well-versed in programming languages, so not even the terminology seems quite correct. So if they're not letting students embrace the whole of the language, they must be concerned with other things? They sloppily emphasize documentation and put in some concerns for procedure signatures. I have some trouble defending it. I see the good intentions, though, and the job is not easy. But this course is definitely not teaching any data structures or any algorithms. Zero. Students are using tuples, lists and dictionaries, strings and numbers, but they're not studying any strategies whatsoever. The exercises make students use a few basic facts of mathematics, but there is pretty much no investigation into the strategies behind some of these facts. It's not very intelligible. I *kinda* like that it's restrictive because it allows us to show students at least a few idioms: otherwise there's so much syntax to digest that there is no time to show a few useful applications of them. But then I read your next paragraph and it brings me to a very important point, which I think it's at the back of your mind too. Let's see. > So... The first thing I would drop is the RESTRICTION to only use what > you've covered in prior sessions... Let the students read the language > reference manual, peruse the library reference manual, and allow them to > use whatever "advanced" techniques they are able to understand on their > own. Precisely. We kill the spirit of investigation by saying --- don't do anything I don't allow you to. This is pretty dangerous. I have a much better idea, I think. You have to give people a tool and say --- use however you want. If we don't want them to use things not introduced in previous lessons, we should give them a precisely-limited tool. But that's not done. The much better idea is to use such a limited language. There are such languages, made precisely for teaching. It comes with very little syntax and lesson after lesson it gets immensely powerful with very little syntax. > Granted you may have to restrict some features if [...] To let students use the entire language feels a bit weird in the sense that the group goes in so many different directions. It definitely put teachers in a position they have to be --- I don't know the answer. It is not my case. But I do think that holding a class with wildly different backgrounds, each going about in their own weird ways is kinda odd. It doesn't seem to bring people together --- on average. The better-idea brings people together by leveling everyone out. Unpopular languages give us this feature. Students hardly ever master them. It's a game nobody played. The rules are very simple. The implications are far-fetching. Sometimes even the programmer-expert in class realizes he is less skilled than the total-novice that never handled a compiler: his tricks don't work in the new game. (It's not that we don't allow him to use them. They're not there. They don't compile.) (We take Ghess players, Backgammon and Checkers players [the students], we teach them a new game, say, Go, and suddenly everyone is learning together. Assume Go is unpopular. It's very simple. Everyone learns the rules quickly and we spend the semester looking into strategies. Much better idea.) > For my Algorithm/Data Structure course (circa 1978), the instructor > allowed us to use any language /he/ could understand (so no SNOBOL). At the > time I'd gone through intro/advanced FORTRAN-4, intro/advanced COBOL, Sigma > Assembly, UCSD Pascal (not on the campus main computer, just a pair of > LSI-11s), and BASIC. The assignment was a "Hashed Head, Multiply-Linked > List". I chose to do that assignment using BASIC! In nearly 45 years, I've > only seen ONE real-world implementation of the HHMLL -- The file system > used by the Commodore Amiga. (Hash the first component of the path/name, > that maps to one of 64 entries in the root directory block; each entry > points the start of a linked list, follow the list until you reach the > block with the component name; if it is a directory block, hash the next > component and repeat; if it is a file block, the "entries" point to data > blocks instead of lists) Repeating my criticism with one more illustration. When ``there's always more than one way to do it'', students can't even count on their classmates to help each other --- because each one is doing a different thing. This is good in science, but what I like the most in schooling is working together and too much freedom like seems not very helpful in this direction. But both worlds is possible. Use a limited tool (which is not computationally limited, quite the contrary) and tell them --- you can do anything you want with this. The effect is that everyone, although everyone is more or less original, the different solutions are never too far apart, so all the exchange is quite possible. From hrouselle at jevedi.com Sat Aug 14 23:40:10 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Sun, 15 Aug 2021 00:40:10 -0300 Subject: some problems for an introductory python test References: <86lf599zse.fsf@jevedi.xotimo> <868s18b1p7.fsf@jevedi.com> Message-ID: <86r1evxtnp.fsf@jevedi.com> Chris Angelico writes: > On Thu, Aug 12, 2021 at 9:23 AM Dennis Lee Bieber wrote: [...] >> I was spoiled by the Amiga variant of REXX. Most current >> implementations (well, Regina is the only one I've looked at) can just pass >> command to the default shell. The Amiga version took advantage of Intuition >> Message Ports (OS supported IPC). That allowed it to "address >> " any application that defined an ARexx port, allowing ARexx >> to be used as a scripting language for that application (and with multiple >> applications, one could easily fetch data from app1 and feed it to app2). >> ARexx did not, to my memory, implement arbitrary precision math. > > The same functionality was available in OS/2, but not heavily used. > You could 'address cmd commandname' to force something to be > interpreted as a shell command, but that was about it. However, I > built a MUD that used REXX as its scripting language, and the default > destination was sending text back to the person who sent the command; > and you could, of course, still 'address cmd' to run a shell command. > >> I've not seen anything equivalent in my light perusal of the Win32 API >> (the various guide books aren't layed out in any way to be a reference), >> and Linux seems to use UNIX sockets for IPC... No way to search for a >> connection point by name... > > Win32 doesn't really have it. Unix sockets are kinda there but you > identify something by a path to the socket, not the name of the > application. But I think dbus is probably the closest to what you're > thinking of. Win32 offers some APIs that sound like it could be what you guys are talking about here that I'm not too clear what it is. There are some shared memory you can reference by name, so it's as easy to use: both applications invoke a procedure with a string-argument and exchange information that way. (And Win32 does support named pipes as well.) I mean I'm sure you know it all better than I do. (Perhaps I'm too clueless here.) I could look up the Win32 APIs I'm thinking of if that would clarify things. From hrouselle at jevedi.com Sun Aug 15 00:04:34 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Sun, 15 Aug 2021 01:04:34 -0300 Subject: some problems for an introductory python test References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86lf599zse.fsf@jevedi.xotimo> <868s18b1p7.fsf@jevedi.com> <868s16zol5.fsf@jevedi.com> Message-ID: <86sfzbwdyl.fsf@jevedi.com> Chris Angelico writes: > On Fri, Aug 13, 2021 at 2:15 AM Hope Rouselle wrote: >> >> Chris Angelico writes: >> >> > History lesson! >> > >> > Once upon a time, IBM and Microsoft looked at what Intel was >> > producing, and went, hey, we need to design an operating system that >> > can take advantage of the fancy features of this 80286 thing. So they >> > collaborate on this plan to make a 16-bit protected mode OS. >> > Unfortunately, things didn't work out too well, partly because this >> > was when Microsoft was at its most monopolistic, and they ended up >> > parting company. IBM continued to make OS/2, but Microsoft took their >> > part of the code and made Windows NT out of it. >> >> How is it possible that Microsoft would take part of the code of OS/2? >> Did IBM just hand it to them? > > I presume both companies had all of the code. It was a matter of > licensing, though. There were a few components that were saddled with > awkward restrictions due to the dual ownership (for instance, HPFS386 > was Microsoft-controlled, but vanilla HPFS was fine - kinda like the > difference between LZW and LZ77). > >> > (Aside: Windows NT's 16-bit applications and OS/2's 16-bit >> > applications were actually identical and compatible. Unfortunately, >> > Win32 introduced a very new API, so as soon as everyone moved to >> > 32-bit everything, the schism became problematic. But it was actually >> > possible to package up a single .EXE file with a 16-bit MS-DOS loader, >> > a Win32 loader, and an OS/2 32-bit loader, all happily coexisting. >> >> Beautiful. :-) So if all libraries were around in each system, they had >> perfect compatibility? > > The 16-bit loaders were fine, but the 32-bit loaders were different, > so this trick basically meant having three different copies of the > code wrapped up in a single executable. > >> > Plus, it had this fancy >> > concept of "extended attributes"; on older systems (like MS-DOS's >> > "FAT" family), a file might be Read-Only, Hidden, a System file, or >> > needing to be Archived, and that was it - but on HPFS, you could >> > attach arbitrary data like "File type: DeScribe Word Processor" or >> > "Double click action: Run CASMake.cmd". This allowed the GUI to store >> > all kinds of information *on the file itself* instead of needing >> > hidden files (or, in Windows' case, the registry) to track that kind >> > of thing. >> >> Yeah, that's kinda nice. Isn't that a UNIX design? A file is a >> sequence of bytes? Users decide what to put in them? So OS/2 was >> taking advantage of that to integrate it well with the system. Windows >> was doing the same, but integrating the system with files in odd ways >> --- such as a registry record to inform the system which programs open >> which files? (That does sound more messy.) > > Something like that, but with a lot more metadata. Modern OSes don't > seem to work that way any more. > >> UNIX's execve() is able to read the first line of an executable and >> invoke its interpreter. I guess OS/2 was doing precisely that in a >> different way? > > Kinda, but instead of having the choice of interpreter be inside the > file contents itself, the choice was in the file's metadata. Still > part of the file, but if you open and read the file, it isn't any > different. Speaking of which, NTFS supports something called file streams. That's essentially a way to have files inside files. Streams are not shown by tools such as file explorer. Applications could definitely use that as metadata. (End of tangent.) I think UNIX people would say and I'd agree --- we have that already. But instead of hiding the stream, which is obscurantism, we let the user see. (Just create two files in a directory, one with the extension .metadata. And, oh, if you don't like that extension, you can change it to whatever you like. Lol.) I like that. >> > The default command interpreter and shell on OS/2 was fairly primitive >> > by today's standards, and was highly compatible with the MS-DOS one, >> > but it also had the ability to run REXX scripts. REXX was *way* ahead >> > of its time. It's a shell language but remarkably well suited to >> > building GUIs and other tools (seriously, can you imagine designing a >> > GUI entirely in a bash script??). >> >> I cannot imagine. I always wondered what REXX was about --- I saw >> programs sometimes written in some website whose name is something like >> Rosetta Code. REXX looked so weird. (``Who would program in that?'') >> But I see now there is a context to it. > > Yeah. It was a strange choice by today's standards, but back then, > most of my GUI programs were written in REXX. > > https://en.wikipedia.org/wiki/VX-REXX > http://www.edm2.com/0206/vrexx.html > > (There were other tools too - VisPro REXX, VREXX, DrDialog, and > various others - but VX-REXX was where most of my dev work happened.) I like that kind of simpler GUI interface. Cleaner. Fast! You know, the so-called ``modern world'' is totally overrated. >> > Probably the most >> > notable feature, by today's standards, was that it had a single input >> > queue. ... This means that, if the response to a >> > keystroke is to change focus, then *even in a slow and lagged out >> > system*, subsequent keys WOULD be sent to the new target window. That >> > was AWESOME, and I really miss it. Except that I also don't. Because >> > if a single application is having issues, now your entire keyboard and >> > mouse is locked up... which kinda slightly sucks. Good luck resolving >> > that problem. (We had some neat tools like WatchCat that could get >> > around the single input queue via interrupt signals, and regain >> > control. But it was still problematic.) >> >> Wow, I kinda feel the same as you here. I think this justifies perhaps >> using a hardware solution. (Crazy idea?! Lol.) > > uhhh........ Yes. Very crazy idea. Can't imagine why anyone would ever > think about doing that. Lol. Really? I mean a certain panic button. You know the GNU Emacs. It has this queue with the implications you mentioned --- as much as it can. (It must of course get the messages from the system, otherwise it can't do anything about it.) And it has the panic button C-g. The keyboard has one the highest precedences in hardware interrupts, doesn't it not? A certain very important system could have a panic button that invokes a certain debugger, say, for a crisis-moment. But then this could be a lousy engineering strategy. I am not an expert at all in any of this. But I'm surprised with your quick dismissal. :-) > Certainly nobody in his right mind would have WatchCat listening on > the serial port's Ring Indicator interrupt, and then grab a paperclip > to bridge the DTR and RI pins on an otherwise-unoccupied serial port > on the back of the PC. (The DTR pin was kept high by the PC, and could > therefore be used as an open power pin to bring the RI high.) Why not? Misuse of hardware? Too precious of a resource? > If you're curious, it's pins 4 and 9 - diagonally up and in from the > short > corner. http://www.usconverters.com/index.php?main_page=page&id=61&chapter=0 You know your pins! That's impressive. I thought the OS itself could use something like that. The fact that they never do... Says something, doesn't it? But it's not too obvious to me. > And of COURSE nobody would ever take an old serial mouse, take the > ball out of it, and turn it into a foot-controlled signal... although > that wasn't for WatchCat, that was for clipboard management between my > app and a Windows accounting package that we used. But that's a > separate story. Lol. I feel you're saying you would. :-) >> Maybe machine and OS >> could have a desktop-version that would have a hardware that could >> effectively be like a second keyboard --- a button. So our keywords >> would have a button that we press it, we could interrupt the OS to >> handle such lock-up more gracefully. I suppose this is expensive, >> complex and so on. But at the same time, it could be worth it. > > SysRq should theoretically be that. (That's Alt+PrtSc on a lot of > keyboards.) I'm not sure how it could best be handled though. It might > be that today's GUI systems (X11, Wayland, Cocoa, Win32, etc) just > wouldn't work with a single input queue. Would be curious to see if > any modern OS/GUI pair has a synchronous input queue like that. I just pressed M-PrtSc on my keyboard. Windows 10. Nothing happened. (I'm not aware of any synchronous input queue liked you said either.) >> > So, yeah. It was spectacular in its day.... but it kinda got left >> > behind as the world moved on. These days, instead of running REXX code >> > on OS/2 in a system that uses eight-bit text for most things, I use >> > Python on Linux and full Unicode. But OS/2 was an important part of >> > history, both my own personal journey, and the history of the world of >> > PCs. >> >> Very nice. Thanks a lot for sharing. I care a lot about such >> histories. In fact, if you could point out from the top of your head >> the best reference on the facts you mentioned here, I would love to >> write it down for future reference. (You probably read books that >> perhaps explained how the queue of windows messages worked et cetera.) >> >> Thank you! > > Thank you for asking questions about it! Aside from making me feel old > (which, let's face it, is kinda inevitable), it's great to dig through > some of the history and a few of the very different ways things have > been done. I am in my early fourties. I can clearly see how kids look at me as old. It's really not so bad. Some are born earlier. :-) And it turns out life a few decades ago was really not so bad. Things seem to be getting rougher now. I feel sorry for kids. What we should do, though, is preserve our health. Older people in good health seem sometimes even happier than the youngsters. > References, unfortunately, are a bit hard to share, since they're > mostly dead-tree books, plus a small number of IPF documents (a format > kinda like man pages, but they get compiled) which have probably been > lost by now. Oh, plus a lot of "My dad told me", which is a bit hard > to point anyone else to :) > > But if you want to delve into things today, I would recommend using > Wikipedia or whatever the almighty Google shows up, neither of which > was available back then, but both of which have vast information > available to you. Some useful topics: > > * Single (or Synchronous) Input Queue > * CORBA (the system for cross-language subclassing of PM classes) > * The OS/2 Presentation Manager > * 80386 Protected Mode > * DBCS (early multilanguage support - appallingly inferior to Unicode, > but better than nothing) > * REXX, VX-REXX, VPREXX, VREXX > * DB2 (IBM's flagship database both then and now; spectacular even > back then, although slow at times) Thank you so much. That's good enough. > Python *was* available on OS/2 back then, but not heavily supported. > It might be interesting to compare the early versions of Python to the > other tools available, but probably more useful to compare the 1990s > tools to modern Python on modern OSes and see how far the world has > come. I heard of Python for the first time in the 90s. I worked at an ISP. Only one guy was really programming there, Allaire ColdFusion. But, odd enough, we used to say we would ``write a script in Python'' when we meant to say we were going out for a smoke. I think that was precisely because nobody knew that ``Python'' really was. I never expected it to be a great language. I imagined it was something like Tcl. (Lol, no offense at all towards Tcl.) From hrouselle at jevedi.com Sun Aug 15 00:10:09 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Sun, 15 Aug 2021 01:10:09 -0300 Subject: some problems for an introductory python test References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86lf599zse.fsf@jevedi.xotimo> <868s18b1p7.fsf@jevedi.com> <868s16zol5.fsf@jevedi.com> Message-ID: <868s13wdpa.fsf@jevedi.com> Grant Edwards writes: > On 2021-08-12, Hope Rouselle wrote: > >>> OS/2 had all kinds of amazing features (for its time). [...] Plus, >>> it had this fancy concept of "extended attributes"; on older >>> systems (like MS-DOS's "FAT" family), a file might be Read-Only, >>> Hidden, a System file, or needing to be Archived, and that was it - >>> but on HPFS, you could attach arbitrary data like "File type: >>> DeScribe Word Processor" or "Double click action: Run >>> CASMake.cmd". This allowed the GUI to store all kinds of >>> information *on the file itself* instead of needing hidden files >>> (or, in Windows' case, the registry) to track that kind of thing. >> >> Yeah, that's kinda nice. Isn't that a UNIX design? A file is a >> sequence of bytes? Users decide what to put in them? > > I think what he's talking about is allowing the user to attach > arbitrary _metadata_ to the file -- metadata that exists separately > and independently from the normal data that's just a "sequence of > bytes". IOW, something similar to the "resource fork" that MacOS used > to have. https://en.wikipedia.org/wiki/Resource_fork Got ya. >> So OS/2 was taking advantage of that to integrate it well with the >> system. Windows was doing the same, but integrating the system with >> files in odd ways --- such as a registry record to inform the system >> which programs open which files? (That does sound more messy.) > > Windows never had filesystems that supported metadata like OS/2 and > MacOS did. The registry was an ugly hack that attempted (very poorly) > to make up for that lack of metadata. Take a look at NTFS streams. Maybe you would consider that as a way to store metadata in Windows. Pavel Yosifovich talks about them briefly in chapter 11, page 555, part 1. Windows 10 System Programming. Here's the first paragraph: --8<---------------cut here---------------start------------->8--- The NTFS filesystem supports /file streams/, which are essentially files within a file. Normally, we use the default data stream, but others can be created and used. These are essentially hidden from normal view and don?t show up in standard tools such as Windows Explorer. --8<---------------cut here---------------end--------------->8--- Pavel Yosifovich wrote a tool to let us see these streams: https://github.com/zodiacon/NtfsStreams >> UNIX's execve() is able to read the first line of an executable and >> invoke its interpreter. I guess OS/2 was doing precisely that in a >> different way? > > No, that's not at all the same thing. The #! line is part of the > normal file data. It's part of the 'sequence of bytes'. Metadata > maintained by Unix filesystems comprises a very limited and > pre-defined set of attributes present in the inode. Well said. From nospam at please.ty Sun Aug 15 04:25:07 2021 From: nospam at please.ty (jak) Date: Sun, 15 Aug 2021 10:25:07 +0200 Subject: Regarding inability of Python Module Winsound to produce beep in decimal frequency References: Message-ID: Il 13/08/2021 18:17, Chris Angelico ha scritto: > On Sat, Aug 14, 2021 at 2:11 AM Terry Reedy wrote: >> >> On 8/13/2021 6:53 AM, Umang Goswami wrote: >>> Hi There, Hope you find this mail in good health. >>> >>> I am Umang Goswami, a Python developer and student working on a huge >>> project for automation of music instruments. I am producing the musical >>> notes using the Beep function of Winsound Module( >>> https://docs.python.org/3/library/winsound.html) by passing frequency as a >>> argument to the function. >>> >>> Now whenever i provide frequency of any note in decimal(for example >>> 277.1826 for C4 note) it shows following error: >>> Traceback (most recent call last): >>> File "C:\Users\Umang Goswami\Desktop\Umang Goswami\test.py", line 2, in >>> >>> winsound.Beep(111.11,111111) >>> TypeError: integer argument expected, got float >>> >>> Now I have to round up the frequencies. This is hurting the quality, >>> accuracy ,authenticity and future of the project. Almost all the notes have >>> the frequencies in decimal parts. Rounding up means changing semitones and >>> quatertones thus whole note itself. This problem is technically making my >>> program useless. >>> > > Is it really? In my experience, no human ear can distinguish 277Hz > from 277.1826Hz when it's played on a one-bit PC speaker, which the > Beep function will be using. > > ChrisA > Hi, you could use a trick to get a better approximation: 277 * 4 = 1108 278 * 1 = 278 1108 + 278 = 1386 1386/5 = 277.2 now, respecting the duration of the tone, in accordance with its simple rate, the buffer to be played will become: 277, 277, 277, 277, 278, 277, 277, 277, 277, 278, 277, 277, ... and so on. From hrouselle at jevedi.com Sun Aug 15 09:19:16 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Sun, 15 Aug 2021 10:19:16 -0300 Subject: some problems for an introductory python test References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86sfzha1ac.fsf@jevedi.xotimo> <86czqkb1z9.fsf@jevedi.com> <865yw7z8f8.fsf@jevedi.com> Message-ID: <86v946voa3.fsf@jevedi.com> Hope Rouselle writes: [...] >> Granted you may have to restrict some features if [...] > > To let students use the entire language feels a bit weird in the sense > that the group goes in so many different directions. It definitely put > teachers in a position they have to be --- I don't know the answer. ^^^^^^^^^^ Sorry. I meant ``they [hate] to be [in] --- I don't know the answer.'' And, alas, I also find many more typos, grammar and cosmetic incoherences below, which I fix with brackets. (Not that they were needed. Only this bit above seemed to lose the meaning of the author, Your Truly.) > It is not my case. But I do think that holding a class with wildly > different backgrounds, each going about in their own weird ways[,] is > kinda odd. It doesn't seem to bring people together --- on average. > > The better-idea brings people together by leveling everyone out. > Unpopular languages give us this feature. Students hardly ever master > them. It's a game nobody played. The rules are very simple. The > implications are far-fetching. Sometimes even the programmer-expert in > class realizes he is less skilled than the total-novice that never > handled a compiler: his tricks don't work in the new game. (It's not > that we don't allow him to use them. They're not there. They don't > compile.) (We take [Chess] players, Backgammon and Checkers players [the > students], we teach them a new game, say, Go, and suddenly everyone is > learning together. Assume Go is unpopular. It's very simple. Everyone > learns the rules quickly and we spend the semester looking into > strategies. Much better idea.) > >> For my Algorithm/Data Structure course (circa 1978), the instructor >> allowed us to use any language /he/ could understand (so no SNOBOL). At the >> time I'd gone through intro/advanced FORTRAN-4, intro/advanced COBOL, Sigma >> Assembly, UCSD Pascal (not on the campus main computer, just a pair of >> LSI-11s), and BASIC. The assignment was a "Hashed Head, Multiply-Linked >> List". I chose to do that assignment using BASIC! In nearly 45 years, I've >> only seen ONE real-world implementation of the HHMLL -- The file system >> used by the Commodore Amiga. (Hash the first component of the path/name, >> that maps to one of 64 entries in the root directory block; each entry >> points the start of a linked list, follow the list until you reach the >> block with the component name; if it is a directory block, hash the next >> component and repeat; if it is a file block, the "entries" point to data >> blocks instead of lists) > > Repeating my criticism with one more illustration. When ``there's > always more than one way to do it'', students can't even count on their > classmates to help each other --- because each one is doing a different > thing. This is good in science, but what I like the most in schooling > is working together and too much freedom like seems not very helpful in > this direction. > > But both worlds [are] possible. Use a limited tool (which is not > computationally limited, quite the contrary) and tell them --- you can > do anything you want with this. [...] [Although] everyone is more or > less original, the different solutions are never too far apart, so all > the exchange is quite possible. From hrouselle at jevedi.com Sun Aug 15 09:50:10 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Sun, 15 Aug 2021 10:50:10 -0300 Subject: on perhaps unloading modules? Message-ID: <86pmueu8a5.fsf@jevedi.com> (*) Introduction By the way, I'm aware that what I'm doing here is totally unsafe and I could get my system destroyed. I'm not planning on using this --- thank you for your concern. I'm just interested in understanding more about modules. (*) The problem I got myself into a mess with loading modules at runtime. The reason I'm loading modules at runtime is because I'm writing a script to grade students' work. (Each student test is a file.py.) Here's the phenomenon. Notice how student m0 (who really scored a zero) first gets his grade right, but if I invoke it again, then it gets 50.0. >>> grade_student(m0) {'grade': 0.0, ...} >>> grade_student(m0) {'grade': 50.0, ...} (*) Where's the problem? The variable m0 is a module and modules in Python are effectively singletons --- that is, they are meant to be loaded only once, no matter how many times you ask the system to. That's my understanding. (*) How did I get into this mess? When m0 is graded first, that is the first student's module ever loaded, so everything turns out correct. This module m0 didn't do any work --- didn't write any procedures, so it gets grade = 0 ---, so when I check the first procedure, it doesn't exist --- zero on question 1. However, question 2 depends on question 1. So I use the test's key (which I wrote, which is perfectly correct) and I augment the student's module with the key's procedures that are prerequisites to question 2 and then I test question 2. How do I do that? I do m.question1 = key.question1 where ``key.question1'' is a correct procedure for getting all points of question1. (That's kind to the student: I'm allowing them to get a zero on question 1 while perhaps getting question 2 right.) However, once I augment the student's code, I can' t find a way to properly restore it to the original --- so on a second execution, m0 gets many more points. That's not the whole problem. For reasons I don't understand, new modules I load --- that is, different students --- get mixed with these modifications in m0 that I made at some point in my code. Of course, you want to see the code. I need to work on producing a small example. Perhaps I will even answer my own question when I do. For now, let me just ignite your imagination. Feel free to ignore all of this and wait for a nice example of the problem. (*) The code How do I load a student's file? --8<---------------cut here---------------start------------->8--- from importlib import * def get_student_module(fname): # Here fname := p1_hello.py. But we need to remove the extension. # Let's call it basename then. mod_name = basename(fname) try: student = import_module(mod_name) except Exception as e: return False, str(e) return True, student --8<---------------cut here---------------end--------------->8--- Now let d be a path to a directory. How do use I this procedure? --8<---------------cut here---------------start------------->8--- for f in get_all_tests(d): okay, student = get_student_module(f) report = grade_student(student) [...] --8<---------------cut here---------------end--------------->8--- What does grade_student(student_module) do? It passes student_module to procedures to check every little thing the test requires. Let's take a look at question4(). Question 4 requires a previous procedure called procedure_x. So I overwrite the student's module with the key's procedure. def question4(m): # We first provide students with all the prerequisites of the # question, so they don't necessarily get this one wrong by getting # prerequisites wrong. m.procedure_x = key.procedure_x # Now I make all my verifications about, say, m.procedure_y and I # compute an integer called losses, which I return. return losses This strategy must be so unwise that it totally breaks my na?ve dream of automatic grading, showing how unfit I am for teaching students how to program. Such is life. (*) If it were easy to unload modules... I could just unload it and load it again. That should restore the student's module back to its original source code. From hrouselle at jevedi.com Sun Aug 15 11:09:58 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Sun, 15 Aug 2021 12:09:58 -0300 Subject: on perhaps unloading modules? References: <86pmueu8a5.fsf@jevedi.com> Message-ID: <86tujqsq0p.fsf@jevedi.com> Hope Rouselle writes: [...] > Of course, you want to see the code. I need to work on producing a > small example. Perhaps I will even answer my own question when I do. [...] Here's a small-enough case. We have two students here. One is called student.py and the other is called other.py. They both get question 1 wrong, but they --- by definition --- get question 2 right. Each question is worth 10 points, so they both should get losses = 10. (*) Student student.py --8<---------------cut here---------------start------------->8--- def question1(t): # right answer is t[2] return t[1] # lack of attention, wrong answer --8<---------------cut here---------------end--------------->8--- (*) Student other.py --8<---------------cut here---------------start------------->8--- def question1(t): # right answer is t[2] return t[0] # also lack of attention, wrong answer --8<---------------cut here---------------end--------------->8--- (*) Grading All is good on first run. Python 3.5.2 [...] on win32 [...] >>> reproducible_problem() student.py, total losses 10 other.py, total losses 10 The the problem: >>> reproducible_problem() student.py, total losses 0 other.py, total losses 0 They lose nothing because both modules are now permanently modified. (*) The code of grading.py --8<---------------cut here---------------start------------->8--- # -*- mode: python; python-indent-offset: 2 -*- def key_question1(t): # Pretty simple. Student must just return index 2 of a tuple. return t[2] def reproducible_problem(): # grade all students okay, m = get_student_module("student.py") r = grade_student(m) print("student.py, total losses", r) # should be 10 okay, m = get_student_module("other.py") r = grade_student(m) print("other.py, total losses", r) # should be 10 def grade_student(m): # grades a single student losses = question1_verifier(m) losses += question2_verifier(m) return losses def question1_verifier(m): losses = 0 if m.question1( (0, 1, 2, 3) ) != 2: # wrong answer losses = 10 return losses def question2_verifier(m): m.question1 = key_question1 # To grade question 2, we overwrite the student's module by giving # it the key_question1 procedure. This way we are able to let the # student get question 2 even if s/he got question 1 incorrect. losses = 0 return losses def get_student_module(fname): from importlib import import_module mod_name = basename(fname) try: student = import_module(mod_name) except Exception as e: return False, str(e) return True, student def basename(fname): # drop the the .py extension return "".join(fname.split(".")[ : -1]) --8<---------------cut here---------------end--------------->8--- From hrouselle at jevedi.com Sun Aug 15 11:48:20 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Sun, 15 Aug 2021 12:48:20 -0300 Subject: on perhaps unloading modules? References: <86pmueu8a5.fsf@jevedi.com> <86tujqsq0p.fsf@jevedi.com> Message-ID: <86lf52so8r.fsf@jevedi.com> Hope Rouselle writes: > Hope Rouselle writes: > > [...] > >> Of course, you want to see the code. I need to work on producing a >> small example. Perhaps I will even answer my own question when I do. > > [...] > > Here's a small-enough case. We have two students here. One is called > student.py and the other is called other.py. They both get question 1 > wrong, but they --- by definition --- get question 2 right. Each > question is worth 10 points, so they both should get losses = 10. > > (*) Student student.py > > def question1(t): # right answer is t[2] > return t[1] # lack of attention, wrong answer > > > (*) Student other.py > > def question1(t): # right answer is t[2] > return t[0] # also lack of attention, wrong answer > > > (*) Grading > > All is good on first run. > > Python 3.5.2 [...] on win32 > [...] >>>> reproducible_problem() > student.py, total losses 10 > other.py, total losses 10 > > The the problem: > >>>> reproducible_problem() > student.py, total losses 0 > other.py, total losses 0 > > They lose nothing because both modules are now permanently modified. > > (*) The code of grading.py > > # -*- mode: python; python-indent-offset: 2 -*- > def key_question1(t): > # Pretty simple. Student must just return index 2 of a tuple. > return t[2] > > def reproducible_problem(): # grade all students > okay, m = get_student_module("student.py") > r = grade_student(m) > print("student.py, total losses", r) # should be 10 > okay, m = get_student_module("other.py") > r = grade_student(m) > print("other.py, total losses", r) # should be 10 > > def grade_student(m): # grades a single student > losses = question1_verifier(m) > losses += question2_verifier(m) > return losses > > def question1_verifier(m): > losses = 0 > if m.question1( (0, 1, 2, 3) ) != 2: # wrong answer > losses = 10 > return losses > > def question2_verifier(m): > m.question1 = key_question1 > # To grade question 2, we overwrite the student's module by giving > # it the key_question1 procedure. This way we are able to let the > # student get question 2 even if s/he got question 1 incorrect. > losses = 0 > return losses My solution is to painfully save each original procedure from student in a variable, replace them with the key's, then restore them at the end. I couldn't overwrite m.__dict__ because it is readonly. (Didn't find a neater's way out.) def question2_verifier(m): question1_original = m.question1 m.question1 = key_question1 # apply verifications... m.question1 = question1_original return losses From greg.ewing at canterbury.ac.nz Mon Aug 16 02:55:45 2021 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Mon, 16 Aug 2021 18:55:45 +1200 Subject: on perhaps unloading modules? In-Reply-To: <86pmueu8a5.fsf@jevedi.com> References: <86pmueu8a5.fsf@jevedi.com> Message-ID: On 16/08/21 1:50 am, Hope Rouselle wrote: > By the way, I'm aware that what I'm doing here is totally unsafe and I > could get my system destroyed. I'm not planning on using this --- thank > you for your concern. I'm just interested in understanding more about > modules. Okay, I'll assume all the security issues have been taken are of, e.g. by running all of this in a virtual machine... > Notice how student m0 (who really scored a zero) > first gets his grade right, but if I invoke it again, then it gets 50.0. The best way to do this would be to run each student's file in a separate process, so you know you're getting a completely fresh start each time. The second best way would be to not use import_module, but to exec() the student's code. That way you don't create an entry in sys.modules and don't have to worry about somehow unloading the module. Something like code = read_student_file(student_name) env = {} # A dict to hold the student's module-level definitions exec(code, env) grade_question1(env) env['procedure_x'] = key.procedure_x grade_question2(env) ...etc... > That's not the whole problem. For reasons I don't understand, new > modules I load --- that is, different students --- get mixed with these > modifications in m0 that I made at some point in my code. I would have to see a specific example of that. One thing to keep in mind is that if key.procedure_x modifies any globals in the key module, it will still modify globals in the key module -- not the student's module -- after being transplanted there. More generally, there are countless ways that a student's code could modify something outside of its own module and affect the behaviour of other student's code. This is why it would be vastly preferable to run each test in a fresh process. > (*) If it were easy to unload modules... It's sometimes possible to unload and reimport a module, but only if the module's effects are completely self-contained. That depends not only on what the module itself does, but what other modules do with it. If any other module has imported it, that module will still contain references to the old module; if there are instances of a class defined in it still existing, they will still be instances of the old version of the class; etc. 99.999% of the time it's easier to just start again with a fresh Python process. -- Greg From hrouselle at jevedi.com Mon Aug 16 07:47:09 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Mon, 16 Aug 2021 08:47:09 -0300 Subject: on perhaps unloading modules? References: <86pmueu8a5.fsf@jevedi.com> Message-ID: <864kbpsjb6.fsf@jevedi.com> Greg Ewing writes: > On 16/08/21 1:50 am, Hope Rouselle wrote: >> By the way, I'm aware that what I'm doing here is totally unsafe and I >> could get my system destroyed. I'm not planning on using this --- thank >> you for your concern. I'm just interested in understanding more about >> modules. > > Okay, I'll assume all the security issues have been taken are of, e.g. > by running all of this in a virtual machine... Oh, good idea. :-D >> Notice how student m0 (who really scored a zero) >> first gets his grade right, but if I invoke it again, then it gets 50.0. > > The best way to do this would be to run each student's file in > a separate process, so you know you're getting a completely fresh > start each time. Yes, that would be much better indeed, but I'd be left with IPC mechanisms of exchanging data. My first idea is to just print out a JSON of the final report to be read by the grader-process. (That is essentially what I'm already doing, except that I don't need to serialize things in a string.) > The second best way would be to not use import_module, but to > exec() the student's code. That way you don't create an entry in > sys.modules and don't have to worry about somehow unloading the > module. > > Something like > > code = read_student_file(student_name) > env = {} # A dict to hold the student's module-level definitions > exec(code, env) > grade_question1(env) > env['procedure_x'] = key.procedure_x > grade_question2(env) > ...etc... That seems a lot easier to implement. >> That's not the whole problem. For reasons I don't understand, new >> modules I load --- that is, different students --- get mixed with these >> modifications in m0 that I made at some point in my code. > > I would have to see a specific example of that. I'm sorry. I don't think I was right in that observation. I tried to produce one such small program to post here and failed. (Let's forget about that.) > One thing to keep in mind is that if key.procedure_x modifies any > globals in the key module, it will still modify globals in the key > module -- not the student's module -- after being transplanted there. > > More generally, there are countless ways that a student's code > could modify something outside of its own module and affect the > behaviour of other student's code. This is why it would be > vastly preferable to run each test in a fresh process. I'm totally convinced. I'll do everything in a fresh process. Having guarantees makes the job much more pleasant to do. >> (*) If it were easy to unload modules... > > It's sometimes possible to unload and reimport a module, but > only if the module's effects are completely self-contained. > That depends not only on what the module itself does, but > what other modules do with it. If any other module has imported > it, that module will still contain references to the old > module; if there are instances of a class defined in it still > existing, they will still be instances of the old version of > the class; etc. > > 99.999% of the time it's easier to just start again with a > fresh Python process. I'm totally convinced. Thank you so much! From janburse at fastmail.fm Sun Aug 15 08:43:23 2021 From: janburse at fastmail.fm (Mostowski Collapse) Date: Sun, 15 Aug 2021 14:43:23 +0200 Subject: ANN: Dogelog Runtime, Prolog to the Moon (2021) Message-ID: Yesterday we went into a little programming binge, despite there was a free parade in Zurich. We could now already implement a transpiler that targets Python. We simply took the transpiler main.p that targets JavaScript and moded it into a new transpiler mainpy.p that targets Python. The code is already on GitHub and we present it also here as the Python code mainpy.p. We were also busy on machine.py and special.py. The progress is now: +------------+ cross +-------------+ | loader.p | compile | loader.py | 100% | compiler.p | -----------> | compiler.py | 100% +------------+ +-------------+ | machine.py | 66% | special.py | 33% +-------------+ See also: Python Version of Dogelog Runtime special https://twitter.com/dogelogch/status/1426884473988292617 Python Version of Dogelog Runtime special https://www.facebook.com/groups/dogelog From johndavidgriner74 at gmail.com Sat Aug 14 18:48:33 2021 From: johndavidgriner74 at gmail.com (John Griner) Date: Sat, 14 Aug 2021 18:48:33 -0400 Subject: Recoding Categorical to Numerical Message-ID: thanks Virus-free. www.avast.com <#m_4567368322047287300_DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2> From Testing at python.nntp.script Sun Aug 15 17:05:27 2021 From: Testing at python.nntp.script (Testing at python.nntp.script) Date: Sun, 15 Aug 2021 21:05:27 -0000 (UTC) Subject: post.py Message-ID: Just got done writing this nice little posting script. Its my first python script ecer so be nice lol. #!/usr/bin/python3 import nntplib import sys NAME = 'testbunny' EMAIL = 'testy at test.com' SIG = 'Testbunny' ORG = 'Python Pirates' SERVER = 'nntp.aioe.org' GROUPS = 'alt.test' SUBJECT = input("What is the subject? ") print("Enter/Paste your content. Ctrl-D or Ctrl-Z ( windows ) to save it.") contents = [] while True: try: BODY = input() contents.append(BODY) except EOFError: break text = '\n'.join(contents) open('article.txt', 'w').close() with open('article.txt', 'a') as f: f.write('From: ' + NAME + " <" + EMAIL + ">") f.write("\n") f.write('Subject: ' + SUBJECT) f.write("\n") f.write('Newsgroups: ' + GROUPS) f.write("\n") f.write('Organization: ' + ORG) f.write("\n") f.write('User-Agent: Python3') f.write("\n") f.write("\n") f.writelines(text) f.write("\n") f.write("\n") f.write('--') f.write("\n") f.write(SIG) f.write("\n") f.write('.') print("Sending article....") s = nntplib.NNTP(SERVER) f = open('article.txt', 'rb') s.post(f) print("done") s.quit() -- Python Test Script . From Testing at python.nntp.script Sun Aug 15 17:08:04 2021 From: Testing at python.nntp.script (testing) Date: Sun, 15 Aug 2021 21:08:04 -0000 (UTC) Subject: fixed the from fiield Message-ID: heh -- Python Test Script . From vitalis.smith at gmail.com Sun Aug 15 21:19:58 2021 From: vitalis.smith at gmail.com (vitalis) Date: Mon, 16 Aug 2021 02:19:58 +0100 Subject: please help Message-ID: <37A553E2-859B-4E07-9C11-63C1221F1DF5@hxcore.ol> I keep getting this error while trying to install pyqt5 designer Fatal error in launcher: Unable to create process using '"c:\program files\python39\python.exe" "C:\Program Files\Python39\Scripts\pip.exe" install PyQt5Designer': The system cannot find the file specified. please what do I do about this Sent from [1]Mail for Windows References Visible links 1. https://go.microsoft.com/fwlink/?LinkId=550986 From rosuav at gmail.com Mon Aug 16 15:21:03 2021 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 17 Aug 2021 05:21:03 +1000 Subject: some problems for an introductory python test In-Reply-To: <86sfzbwdyl.fsf@jevedi.com> References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86lf599zse.fsf@jevedi.xotimo> <868s18b1p7.fsf@jevedi.com> <868s16zol5.fsf@jevedi.com> <86sfzbwdyl.fsf@jevedi.com> Message-ID: On Tue, Aug 17, 2021 at 3:51 AM Hope Rouselle wrote: > > Chris Angelico writes: > >> Wow, I kinda feel the same as you here. I think this justifies perhaps > >> using a hardware solution. (Crazy idea?! Lol.) > > > > uhhh........ Yes. Very crazy idea. Can't imagine why anyone would ever > > think about doing that. > > Lol. Really? I mean a certain panic button. You know the GNU Emacs. > It has this queue with the implications you mentioned --- as much as it > can. (It must of course get the messages from the system, otherwise it > can't do anything about it.) And it has the panic button C-g. The > keyboard has one the highest precedences in hardware interrupts, doesn't > it not? A certain very important system could have a panic button that > invokes a certain debugger, say, for a crisis-moment. > > But then this could be a lousy engineering strategy. I am not an expert > at all in any of this. But I'm surprised with your quick dismissal. :-) > > > Certainly nobody in his right mind would have WatchCat listening on > > the serial port's Ring Indicator interrupt, and then grab a paperclip > > to bridge the DTR and RI pins on an otherwise-unoccupied serial port > > on the back of the PC. (The DTR pin was kept high by the PC, and could > > therefore be used as an open power pin to bring the RI high.) > > Why not? Misuse of hardware? Too precious of a resource? > > > If you're curious, it's pins 4 and 9 - diagonally up and in from the > > short > > corner. http://www.usconverters.com/index.php?main_page=page&id=61&chapter=0 > > You know your pins! That's impressive. I thought the OS itself could > use something like that. The fact that they never do... Says something, > doesn't it? But it's not too obvious to me. > > > And of COURSE nobody would ever take an old serial mouse, take the > > ball out of it, and turn it into a foot-controlled signal... although > > that wasn't for WatchCat, that was for clipboard management between my > > app and a Windows accounting package that we used. But that's a > > separate story. > > Lol. I feel you're saying you would. :-) This was all a figure of speech, and the denials were all tongue in cheek. Not only am I saying we would, but we *did*. All of the above. The Ring Indicator trick was one of the best, since we had very little other use for serial ports, and it didn't significantly impact the system during good times, but was always reliable when things went wrong. (And when I posted it, I could visualize the port and knew which pins to bridge, but had to go look up a pinout to be able to say their pin numbers and descriptions.) > I heard of Python for the first time in the 90s. I worked at an ISP. > Only one guy was really programming there, Allaire ColdFusion. But, odd > enough, we used to say we would ``write a script in Python'' when we > meant to say we were going out for a smoke. I think that was precisely > because nobody knew that ``Python'' really was. I never expected it to > be a great language. I imagined it was something like Tcl. (Lol, no > offense at all towards Tcl.) Haha, that's a weird idiom! Funny you should mention Tcl. https://docs.python.org/3/library/tkinter.html ChrisA From python at mrabarnett.plus.com Mon Aug 16 15:24:17 2021 From: python at mrabarnett.plus.com (MRAB) Date: Mon, 16 Aug 2021 20:24:17 +0100 Subject: please help In-Reply-To: <37A553E2-859B-4E07-9C11-63C1221F1DF5@hxcore.ol> References: <37A553E2-859B-4E07-9C11-63C1221F1DF5@hxcore.ol> Message-ID: <30b0456a-0549-b2aa-b8f0-b0d9c8efded9@mrabarnett.plus.com> On 2021-08-16 02:19, vitalis wrote: > I keep getting this error while trying to install pyqt5 designer > > Fatal error in launcher: Unable to create process using '"c:\program > files\python39\python.exe" "C:\Program Files\Python39\Scripts\pip.exe" > install PyQt5Designer': The system cannot find the file specified. > > please what do I do about this > Try using the Python Launcher and the pip module: py -3.9 -m install PyQt5Designer From rosuav at gmail.com Mon Aug 16 15:24:26 2021 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 17 Aug 2021 05:24:26 +1000 Subject: on perhaps unloading modules? In-Reply-To: References: <86pmueu8a5.fsf@jevedi.com> Message-ID: On Tue, Aug 17, 2021 at 4:02 AM Greg Ewing wrote: > The second best way would be to not use import_module, but to > exec() the student's code. That way you don't create an entry in > sys.modules and don't have to worry about somehow unloading the > module. I would agree with this. If you need to mess around with modules and you don't want them to be cached, avoid the normal "import" mechanism, and just exec yourself a module's worth of code. ChrisA From abhi.darkness at gmail.com Mon Aug 16 15:28:43 2021 From: abhi.darkness at gmail.com (Abhiram R) Date: Tue, 17 Aug 2021 00:58:43 +0530 Subject: some problems for an introductory python test In-Reply-To: <868s1acoo1.fsf@jevedi.xotimo> References: <868s1acoo1.fsf@jevedi.xotimo> Message-ID: Hello, One of my absolute favorite places to go to practice Python questions from is https://projecteuler.net . It's just Maths based questions that cannot be solved by hand without consuming a Ton of time because of the high limits. This is how I learnt Python. By solving problems from the site in Python! Happy to provide more tips wrt this if required. Regards Abhi R On Tue, Aug 10, 2021 at 2:56 AM Hope Rouselle wrote: > I'm looking for questions to put on a test for students who never had > any experience with programming, but have learned to use Python's > procedures, default arguments, if-else, strings, tuples, lists and > dictionaries. (There's no OOP at all in this course. Students don't > even write ls.append(...). They write list.append(ls, ...)). > > I'd like to put questions that they would have to write procedures that > would would be real-world type of stuff, without error checking, > exceptions and such. So if you think of something more or less cool > that uses loops, we can sometimes simplify it by assuming the input has > a certain fixed size. > > I came up with the following question. Using strings of length 5 > (always), write a procedure histogram(s) that consumes a string and > produces a dictionary whose keys are each substrings (of the string) of > length 1 and their corresponding values are the number of times each > such substrings appear. For example, histogram("aaaaa") = {"a": 5}. > Students can "loop through" the string by writing out s[0], s[1], s[2], > s[3], s[4]. > > I'd like even better questions. I'd like questions that would tell them > to write procedures that would also have inverses, so that one could > check the other of the other. (A second question would ask for the > inverse, but hopefully real world stuff. One such question could be > parsing a line separate by fields such as "root:0:0:mypass:Super User" > and another that gives them ["root", 0, 0, ...] and asks them to write > "root:0:0:mypass:..." You get the idea.) > > Students know how to use str(). But they don't know how to use type(), > so they can't really check for the type of the input. I probably > couldn't ask them to write a prototype of a tiny subset of pickle, say. > > I think you get the idea. I hope you can provide me with creativity. I > have been looking at books, but every one I look at they introduce loops > very quickly and off they go. Thank you! > -- > https://mail.python.org/mailman/listinfo/python-list > -- -Abhiram R From wlfraed at ix.netcom.com Mon Aug 16 20:03:45 2021 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Mon, 16 Aug 2021 20:03:45 -0400 Subject: on slices, negative indices, which are the equivalent procedures? References: <86sfznhk1f.fsf@example.com> <86wnos9ge8.fsf@jevedi.com> <4vi8hg1tfcd2vsrchgpnbpf9a9l7acf7rl@4ax.com> <86a6lj1k7a.fsf@jevedi.com> Message-ID: On Sun, 15 Aug 2021 00:05:29 -0300, Jack Brandom declaimed the following: >Dennis Lee Bieber writes: > >> subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] >> sliceop: ':' [test] > >This is looking less readable, so, no, I prefer that previous, which was >much clearer about slices. I can't even quite make the slices out in >these rules. (But thanks for the opportunity to try.) The last part of "subscript" has the main "slice" notation (stripping the quotes) [test] : [test] and the "stride" component is [sliceop] being : [test] -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From wlfraed at ix.netcom.com Mon Aug 16 20:17:55 2021 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Mon, 16 Aug 2021 20:17:55 -0400 Subject: please help References: <37A553E2-859B-4E07-9C11-63C1221F1DF5@hxcore.ol> <30b0456a-0549-b2aa-b8f0-b0d9c8efded9@mrabarnett.plus.com> Message-ID: On Mon, 16 Aug 2021 20:24:17 +0100, MRAB declaimed the following: >On 2021-08-16 02:19, vitalis wrote: >> I keep getting this error while trying to install pyqt5 designer >> >> Fatal error in launcher: Unable to create process using '"c:\program >> files\python39\python.exe" "C:\Program Files\Python39\Scripts\pip.exe" >> install PyQt5Designer': The system cannot find the file specified. >> >> please what do I do about this >> >Try using the Python Launcher and the pip module: > > py -3.9 -m install PyQt5Designer py-3.9 -m pip install PyQt5Designer... However I would want to see the exact command line (not whatever reformatting took place in the error message). Literal reading of that message implies the OP is trying to pass a pip EXECUTABLE as the program to be run by Python, rather than a pip .py file. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From wlfraed at ix.netcom.com Mon Aug 16 21:28:10 2021 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Mon, 16 Aug 2021 21:28:10 -0400 Subject: some problems for an introductory python test References: <86lf599zse.fsf@jevedi.xotimo> <868s18b1p7.fsf@jevedi.com> <86o89zz9ch.fsf@jevedi.com> Message-ID: On Sun, 15 Aug 2021 00:15:58 -0300, Hope Rouselle declaimed the following: Giganews seems to have just vomited up three days worth of traffic... >Dennis Lee Bieber writes: > >> >> Granted, the fact that the Amiga used a shared common address space for >> all running applications made IPC quite easy -- one looked up the >> application message port, then added a small packet to the linked list >> associated with the port. That small packet basically held the address of >> the message port for returning data, and the address of the data being >> passed. The closet thing I've seen to that capability on systems with >> process-isolated virtual memory is (Open)VMS "mailbox" structures. The >> difference being that the entire data had to be written (QIO) to the >> mailbox, and the receiver had to read (another QIO call) the message -- >> this allowed the address space to change. >> >> I've not seen anything equivalent in my light perusal of the Win32 API >> (the various guide books aren't layed out in any way to be a reference), >> and Linux seems to use UNIX sockets for IPC... No way to search for a >> connection point by name... > >I don't know anything about Amiga, REXX et cetera, so I might be totall >off here. But since you spoke of your perusal of the Win32 API, let me >add a tiny bit. I gave myself a quick tour through the Win32 API using >Pavel Yosifovich's book ``Windows 10 System Programming''. It's a two >volume work. The thing that impressed me the most was the many ways to >do the IPC. The purpose the work is clearly to show what is available >and it it probably does the job well. (I ignored Windows for most of my >life and now I decided to take a look at it. I don't feel it has much >of the elegance of UNIX. It's what it is.) For a book that was published only a year ago -- it seems to be hard to find... Amazon has v1, but not v2. I have the "Windows Internals 6th" both volumes. The closet those get to IPC is something called ALPC -- and that is declared to be internal only, not available to third party programmers. "Programming Windows 6th" is focused on using C# (which, for the most part, means using the "managed" API, not the Win32 API directly). "Mailslots" (I'm using Google to find Windows IPC options) initially sound close to Amiga message ports... Except there is no status return inherent to the system; Amiga messages contain a return address so a program can wait for the status of processing by the destination address. They also don't qualify as VMS mailboxes as there can only be one reader (the creator of the mailslot). VMS mailboxes allow multiple writers and/or multiple readers. "File mapping" doesn't provide any form of queuing -- multiple "writers" would require manually implementing some protocol to track "next available space" in the mapped file. It would allow bidirectional message passing, but again that requires some rather nasty overhead information (when is the return status valid -- it is presumed the client wanting the return status would get it from the same memory space as the message it sent, and that space can't be reused until the client explicitly frees it -- again by some overhead protocol changing headers of free space. "Data Copy" also sounds close to Amiga message ports (closer than "Mailslots"), but the online documentation doesn't indicate if it queues messages. The documentation doesn't illustrate HOW to return TRUE or FALSE (processed/rejected). It advices that the receiver should treat the data as read-only -- though I have to wonder if it /could/ write a return status into the same message structure before "returning TRUE". Named Pipes and Sockets both have the "tied to endpoints" problem, and in the case of Pipes, may only allow one sender to connect at a time (sockets are also one connection, but normally the receivers spawns a thread for each active connection and the connections are made using different allocated sockets). -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From eryksun at gmail.com Mon Aug 16 21:43:11 2021 From: eryksun at gmail.com (Eryk Sun) Date: Mon, 16 Aug 2021 20:43:11 -0500 Subject: Regarding inability of Python Module Winsound to produce beep in decimal frequency In-Reply-To: <6068cc72-6377-458d-0bde-35919f327782@roelschroeven.net> References: <396db396-272b-b7a4-2daf-92e26d005535@mrabarnett.plus.com> <20210815130117.03c23726@e7240.home> <6068cc72-6377-458d-0bde-35919f327782@roelschroeven.net> Message-ID: On 8/16/21, Roel Schroeven wrote: > > We're not necessarily talking about the PC speaker here: (almost) all > computers these days have sound cards (mostly integrated on the > motherboard) that are much more capable than those one-bit PC speakers. Yes, the PC speaker beep does not get used in Windows 7+. The beep device object is retained for compatibility, but it redirects the request to a task in the user's session (which could be a remote desktop session) that generates a WAV buffer in memory and plays it via PlaySound(). You can do this yourself if you need a more precise frequency. For example: import io import math import wave import winsound def beep(frequency, duration): '''Play a beep at frequency (hertz) for duration (milliseconds).''' fs = 48000 f = 2 * math.pi * frequency / fs n = round(duration * fs / 1000) b = io.BytesIO() w = wave.Wave_write(b) w.setnchannels(1) w.setsampwidth(2) w.setframerate(fs) w.writeframes(b''.join(round(32767 * math.sin(f*i)).to_bytes( 2, 'little', signed=True) for i in range(n))) w.close() winsound.PlaySound(b.getbuffer(), winsound.SND_MEMORY) Play a beep at 277.1826 Hz for one second: beep(277.1826, 1000) I'm tone deaf, I suppose, since I need a difference of about 3 cycles to perceive it, let alone a fraction of a cycle. From rosuav at gmail.com Mon Aug 16 23:00:42 2021 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 17 Aug 2021 13:00:42 +1000 Subject: Regarding inability of Python Module Winsound to produce beep in decimal frequency In-Reply-To: References: <396db396-272b-b7a4-2daf-92e26d005535@mrabarnett.plus.com> <20210815130117.03c23726@e7240.home> <6068cc72-6377-458d-0bde-35919f327782@roelschroeven.net> Message-ID: On Tue, Aug 17, 2021 at 11:44 AM Eryk Sun wrote: > > On 8/16/21, Roel Schroeven wrote: > > > > We're not necessarily talking about the PC speaker here: (almost) all > > computers these days have sound cards (mostly integrated on the > > motherboard) that are much more capable than those one-bit PC speakers. > > Yes, the PC speaker beep does not get used in Windows 7+. The beep > device object is retained for compatibility, but it redirects the > request to a task in the user's session (which could be a remote > desktop session) that generates a WAV buffer in memory and plays it > via PlaySound(). That seems a bizarre way to handle it. What happens if you have multiple sound cards? Or if a program needs to get the user's attention despite headphones being connected to the sound card? That's what the PC speaker is for, and I would be quite surprised if Windows just says "nahh that doesn't matter". ChrisA From eryksun at gmail.com Mon Aug 16 23:50:17 2021 From: eryksun at gmail.com (Eryk Sun) Date: Mon, 16 Aug 2021 22:50:17 -0500 Subject: Regarding inability of Python Module Winsound to produce beep in decimal frequency In-Reply-To: References: <396db396-272b-b7a4-2daf-92e26d005535@mrabarnett.plus.com> <20210815130117.03c23726@e7240.home> <6068cc72-6377-458d-0bde-35919f327782@roelschroeven.net> Message-ID: On 8/16/21, Chris Angelico wrote: > On Tue, Aug 17, 2021 at 11:44 AM Eryk Sun wrote: > >> Yes, the PC speaker beep does not get used in Windows 7+. The beep >> device object is retained for compatibility, but it redirects the >> request to a task in the user's session (which could be a remote >> desktop session) that generates a WAV buffer in memory and plays it >> via PlaySound(). > > That seems a bizarre way to handle it. Check the documentation [1]: In Windows 7, Beep was rewritten to pass the beep to the default sound device for the session. This is normally the sound card, except when run under Terminal Services, in which case the beep is rendered on the client. I didn't just take their word for it, however. I checked the code for "\Device\Beep" in a kernel debugger. It gets the session ID to find and complete the I/O Request Packet (IRP) that was queued up by the per-session multimedia task (in Windows device drivers, this is called an inverted call [2]). I attached a debugger to the taskhostw.exe process that's hosting the multimedia task -- in particular the PlaySoundSrv.dll module -- and followed what it did to play a beep. The implementation is in a CBeepRedirector class, in particular its WorkThread() method handles the completed IOCTL from the beep device by calling the DoPlaySound() method, which calls Generate16bitMonoTone() to create a sine wave in WAV format, and plays it via PlaySound() with the SND_MEMORY flag. > multiple sound cards? PlaySound() and system sounds use the default audio output device. If it's an RDP session, the audio is redirected to the client-side device stack. > attention despite headphones being connected to the sound card? An application that wants the user's attention can also flash the window caption and/or taskbar button via FlashWindowEx(). --- [1] https://docs.microsoft.com/en-us/windows/win32/api/utilapiset/nf-utilapiset-beep [2] https://www.osr.com/nt-insider/2013-issue1/inverted-call-model-kmdf From rosuav at gmail.com Tue Aug 17 01:11:05 2021 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 17 Aug 2021 15:11:05 +1000 Subject: Regarding inability of Python Module Winsound to produce beep in decimal frequency In-Reply-To: References: <396db396-272b-b7a4-2daf-92e26d005535@mrabarnett.plus.com> <20210815130117.03c23726@e7240.home> <6068cc72-6377-458d-0bde-35919f327782@roelschroeven.net> Message-ID: On Tue, Aug 17, 2021 at 1:50 PM Eryk Sun wrote: > > On 8/16/21, Chris Angelico wrote: > > On Tue, Aug 17, 2021 at 11:44 AM Eryk Sun wrote: > > > >> Yes, the PC speaker beep does not get used in Windows 7+. The beep > >> device object is retained for compatibility, but it redirects the > >> request to a task in the user's session (which could be a remote > >> desktop session) that generates a WAV buffer in memory and plays it > >> via PlaySound(). > > > > That seems a bizarre way to handle it. > > Check the documentation [1]: > > In Windows 7, Beep was rewritten to pass the beep to the default sound > device for the session. This is normally the sound card, except when > run under Terminal Services, in which case the beep is rendered on the > client. > Huh. Okay. Then I withdraw the concern from this list, and instead lay it at Microsoft's feet. That is, I maintain, a bizarre choice. Surely there are better ways to trigger audio on the sound card? ChrisA From arj.python at gmail.com Tue Aug 17 06:45:53 2021 From: arj.python at gmail.com (Abdur-Rahmaan Janhangeer) Date: Tue, 17 Aug 2021 14:45:53 +0400 Subject: FlaskCon's Call For Volunteers Is On Message-ID: Greetings list, As preparations for FlaskCon intensifies, the call for volunteers goes live: https://twitter.com/FlaskCon/status/1427542892642410502?s=20 You can also chip in directly here: https://docs.google.com/forms/d/e/1FAIpQLSfsHNBcclWSmVkk4LDD_EnlhrlKdWlGOakdwbt5PbaFklpHAA/viewform According to previsions, it might be the last Python conf of the year! Kind Regards, Abdur-Rahmaan Janhangeer about | blog github Mauritius From martinp.dipaola at gmail.com Tue Aug 17 09:41:16 2021 From: martinp.dipaola at gmail.com (Martin Di Paola) Date: Tue, 17 Aug 2021 13:41:16 +0000 Subject: on perhaps unloading modules? In-Reply-To: <86tujqsq0p.fsf@jevedi.com> References: <86pmueu8a5.fsf@jevedi.com> <86tujqsq0p.fsf@jevedi.com> Message-ID: <20210817134116.r5gec64gkb53fdma@gmail.com> This may not answer your question but it may provide an alternative solution. I had the same challenge that you an year ago so may be my solution will work for you too. Imagine that you have a Markdown file that *documents* the expected results. --8<---------------cut here---------------start------------->8--- This is the final exam, good luck! First I'm going to load your code (the student's code): ```python >>> import student ``` Let's see if you programmed correctly a sort algorithm ```python >>> data = [3, 2, 1, 3, 1, 9] >>> student.sort_numbers(data) [1, 1, 2, 3, 3, 9] ``` Let's now if you can choose the correct answer: ```python >>> t = ["foo", "bar", "baz"] >>> student.question1(t) "baz" ``` --8<---------------cut here---------------end--------------->8--- Now you can run the snippets of code with: byexample -l python the_markdown_file.md What byexample does is to run the Python code, capture the output and compare it with the expected result. In the above example "student.sort_numbers" must return the list sorted. That output is compared by byexample with the list written below. Advantages? Each byexample run is independent of the other and the snippet of codes are executed in a separated Python process. byexample takes care of the IPC. I don't know the details of your questions so I'm not sure if byexample will be the tool for you. In my case I evaluate my students giving them the Markdown and asking them to code the functions so they return the expected values. Depending of how many students you have you may considere to complement this with INGInious. It is designed to run students' assignments assuming nothing on the untrusted code. Links: https://byexamples.github.io/byexample/ https://docs.inginious.org/en/v0.7/ On Sun, Aug 15, 2021 at 12:09:58PM -0300, Hope Rouselle wrote: >Hope Rouselle writes: > >[...] > >> Of course, you want to see the code. I need to work on producing a >> small example. Perhaps I will even answer my own question when I do. > >[...] > >Here's a small-enough case. We have two students here. One is called >student.py and the other is called other.py. They both get question 1 >wrong, but they --- by definition --- get question 2 right. Each >question is worth 10 points, so they both should get losses = 10. > >(*) Student student.py > >--8<---------------cut here---------------start------------->8--- >def question1(t): # right answer is t[2] > return t[1] # lack of attention, wrong answer >--8<---------------cut here---------------end--------------->8--- > >(*) Student other.py > >--8<---------------cut here---------------start------------->8--- >def question1(t): # right answer is t[2] > return t[0] # also lack of attention, wrong answer >--8<---------------cut here---------------end--------------->8--- > >(*) Grading > >All is good on first run. > >Python 3.5.2 [...] on win32 >[...] >>>> reproducible_problem() >student.py, total losses 10 >other.py, total losses 10 > >The the problem: > >>>> reproducible_problem() >student.py, total losses 0 >other.py, total losses 0 > >They lose nothing because both modules are now permanently modified. > >(*) The code of grading.py > >--8<---------------cut here---------------start------------->8--- ># -*- mode: python; python-indent-offset: 2 -*- >def key_question1(t): > # Pretty simple. Student must just return index 2 of a tuple. > return t[2] > >def reproducible_problem(): # grade all students > okay, m = get_student_module("student.py") > r = grade_student(m) > print("student.py, total losses", r) # should be 10 > okay, m = get_student_module("other.py") > r = grade_student(m) > print("other.py, total losses", r) # should be 10 > >def grade_student(m): # grades a single student > losses = question1_verifier(m) > losses += question2_verifier(m) > return losses > >def question1_verifier(m): > losses = 0 > if m.question1( (0, 1, 2, 3) ) != 2: # wrong answer > losses = 10 > return losses > >def question2_verifier(m): > m.question1 = key_question1 > # To grade question 2, we overwrite the student's module by giving > # it the key_question1 procedure. This way we are able to let the > # student get question 2 even if s/he got question 1 incorrect. > losses = 0 > return losses > >def get_student_module(fname): > from importlib import import_module > mod_name = basename(fname) > try: > student = import_module(mod_name) > except Exception as e: > return False, str(e) > return True, student > >def basename(fname): # drop the the .py extension > return "".join(fname.split(".")[ : -1]) >--8<---------------cut here---------------end--------------->8--- >-- >https://mail.python.org/mailman/listinfo/python-list From joepareti54 at gmail.com Tue Aug 17 11:50:59 2021 From: joepareti54 at gmail.com (joseph pareti) Date: Tue, 17 Aug 2021 17:50:59 +0200 Subject: question on trax Message-ID: In the following code, where does tl.Fn come from? i see it nowhere in the documents, i.e I was looking for trax.layers.Fn : import numpy as np *from trax import layers as tl* from trax import shapes from trax import fastmath # def Addition(): layer_name = "Addition" # don't forget to give your custom layer a name to identify # Custom function for the custom layer def func(x, y): return x + y return *tl.Fn*(layer_name, func) # Test it add = Addition() # Inspect properties print("-- Properties --") print("name :", add.name) print("expected inputs :", add.n_in) print("promised outputs :", add.n_out, "\n") # Inputs x = np.array([3]) y = np.array([4]) print("-- Inputs --") print("x :", x, "\n") print("y :", y, "\n") # Outputs z = add((x, y)) print("-- Outputs --") print("z :", z) -- Regards, Joseph Pareti - Artificial Intelligence consultant Joseph Pareti's AI Consulting Services https://www.joepareti54-ai.com/ cell +49 1520 1600 209 cell +39 339 797 0644 From robin at reportlab.com Tue Aug 17 05:20:37 2021 From: robin at reportlab.com (Robin Becker) Date: Tue, 17 Aug 2021 10:20:37 +0100 Subject: basic auth request Message-ID: <07b8928a-fe1f-958b-3ee2-d0f6ec51d414@everest.reportlab.co.uk> While porting an ap from python2.7 to python3 I see this base64string = base64.b64encode('%s:%s' % (wsemail, wspassword)) request.add_header("Authorization", "Basic %s" % base64string) in python3.x I find this works base64string = base64.b64encode(('%s:%s' % (wsemail, wspassword)).encode('ascii')).decode('ascii') request.add_header("Authorization", "Basic %s" % base64string) but I find the conversion to and from ascii irksome. Is there a more direct way to create the basic auth value? As an additional issue I find I have no clear idea what encoding is allowed for the components of a basic auth input. -- Robin Becker From wlfraed at ix.netcom.com Tue Aug 17 11:04:58 2021 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Tue, 17 Aug 2021 11:04:58 -0400 Subject: Regarding inability of Python Module Winsound to produce beep in decimal frequency References: <20210815130117.03c23726@e7240.home> <6068cc72-6377-458d-0bde-35919f327782@roelschroeven.net> Message-ID: On Tue, 17 Aug 2021 15:11:05 +1000, Chris Angelico declaimed the following: > >Huh. Okay. Then I withdraw the concern from this list, and instead lay >it at Microsoft's feet. That is, I maintain, a bizarre choice. Surely >there are better ways to trigger audio on the sound card? > Possibly there is a section of code that determines if a sound card is available, and if not, routes to the basic internal speaker. The rest of the wave form logic is probably still of use for that. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From nikhilsoniyar2384 at gmail.com Tue Aug 17 05:59:33 2021 From: nikhilsoniyar2384 at gmail.com (hi) Date: Tue, 17 Aug 2021 15:29:33 +0530 Subject: connection aborted error please help to fix it Message-ID: <75A8086F-BFBB-4D38-A8BA-E1C201BA8DF1@hxcore.ol> Sent from [1]Mail for Windows References Visible links 1. https://go.microsoft.com/fwlink/?LinkId=550986 From rosuav at gmail.com Tue Aug 17 13:16:27 2021 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 18 Aug 2021 03:16:27 +1000 Subject: basic auth request In-Reply-To: <07b8928a-fe1f-958b-3ee2-d0f6ec51d414@everest.reportlab.co.uk> References: <07b8928a-fe1f-958b-3ee2-d0f6ec51d414@everest.reportlab.co.uk> Message-ID: On Wed, Aug 18, 2021 at 3:04 AM Robin Becker wrote: > > While porting an ap from python2.7 to python3 I see this > > base64string = base64.b64encode('%s:%s' % (wsemail, wspassword)) > request.add_header("Authorization", "Basic %s" % base64string) > > in python3.x I find this works > > base64string = base64.b64encode(('%s:%s' % (wsemail, wspassword)).encode('ascii')).decode('ascii') > request.add_header("Authorization", "Basic %s" % base64string) > > but I find the conversion to and from ascii irksome. Is there a more direct way to create the basic auth value? > > As an additional issue I find I have no clear idea what encoding is allowed for the components of a basic auth input. Hmm, I'm not sure what type your wsemail and wspassword are, but one option would be to use bytes everywhere (assuming your text is all ASCII). wsemail = b"robin at becker.example" wspassword = b"correct-battery-horse-staple" base64string = base64.b64encode(b'%s:%s' % (wsemail, wspassword)) But otherwise, it's probably safest to keep using the encode and decode. As to the appropriate encoding, that's unclear according to the standard, but UTF-8 is probably acceptable. ASCII is also safe, as it'll safely error out if it would be ambiguous. https://stackoverflow.com/questions/7242316/what-encoding-should-i-use-for-http-basic-authentication ChrisA From python at mrabarnett.plus.com Tue Aug 17 13:17:43 2021 From: python at mrabarnett.plus.com (MRAB) Date: Tue, 17 Aug 2021 18:17:43 +0100 Subject: question on trax In-Reply-To: References: Message-ID: On 2021-08-17 16:50, joseph pareti wrote: > In the following code, where does tl.Fn come from? i see it nowhere in the > documents, i.e I was looking for trax.layers.Fn : > > import numpy as np > *from trax import layers as tl* > from trax import shapes > from trax import fastmath > # > def Addition(): > layer_name = "Addition" # don't forget to give your custom layer a > name to identify > > # Custom function for the custom layer > def func(x, y): > return x + y > > return *tl.Fn*(layer_name, func) > [snip] It comes from using the line: from trax import layers as tl so it's equivalent to 'trax.layers.Fn'. From barry at barrys-emacs.org Tue Aug 17 14:05:15 2021 From: barry at barrys-emacs.org (Barry Scott) Date: Tue, 17 Aug 2021 19:05:15 +0100 Subject: Cyclic imports In-Reply-To: References: Message-ID: <11811693.O9o76ZdvQC@varric.chelsea.private> On Monday, 16 August 2021 16:13:47 BST Dan Stromberg wrote: > Hi folks. > > I'm working on a large codebase that has at least one cyclic import. > > In case I end up needing to eliminate the cyclic imports, is there any sort > of tool that will generate an import graph and output Just the cycles? > > I tried pyreverse, but it produced too big a graph to be very useful; it > showed all internal imports, not just the cycles. I wrote this code to track down a cycling import. Note it handles import module, but not from module import. You would need to make a (simple) edit to add that. ---- py_import_time.py --- #!/usr/bin/python3 import sys import pathlib class PyImportTree: def __init__( self, main_module, python_path ): self.main_module = main_module self.python_path = python_path self.all_modules = {} self.loadTree( self.main_module ) self.all_being_imported = set() self.problem_imports = 0 def loadTree( self, module_name ): all_imports = self.allImports( module_name ) if all_imports is None: return self.all_modules[ module_name ] = all_imports for module in all_imports: if module not in self.all_modules: self.loadTree( module ) def findModule( self, module_name ): for folder in self.python_path: abs_path = pathlib.Path( folder ) / ('%s.py' % (module_name,)) if abs_path.exists(): return abs_path return None def allImports( self, module_name ): all_imports = [] filename = self.findModule( module_name ) if filename is None: print( 'Error: Cannot find module %s' % (module_name,), file=sys.stderr ) return None with open( str(filename), 'r' ) as f: for line in f: words = line.strip().split() if words[0:1] == ['import']: all_imports.append( words[1] ) return all_imports def printTree( self ): self.__printTree( self.main_module, 0 ) if self.problem_imports > 0: print( '%d problem imports' % (self.problem_imports,), file=sys.stderr ) def __printTree( self, module_name, indent ): if module_name not in self.all_modules: return if module_name in self.all_being_imported: print( '%s%s' % ('> '*indent, module_name) ) self.problem_imports += 1 return print( '%s%s' % ('- '*indent, module_name) ) self.all_being_imported.add( module_name ) for module in self.all_modules[ module_name ]: self.__printTree( module, indent+1 ) self.all_being_imported.remove( module_name ) if __name__ == '__main__': sys.setrecursionlimit( 30 ) sys.exit( PyImportTree( sys.argv[1], sys.argv[2:] ).printTree() ) From barry at barrys-emacs.org Tue Aug 17 14:15:18 2021 From: barry at barrys-emacs.org (Barry Scott) Date: Tue, 17 Aug 2021 19:15:18 +0100 Subject: basic auth request In-Reply-To: <07b8928a-fe1f-958b-3ee2-d0f6ec51d414@everest.reportlab.co.uk> References: <07b8928a-fe1f-958b-3ee2-d0f6ec51d414@everest.reportlab.co.uk> Message-ID: <4647390.GXAFRqVoOG@varric.chelsea.private> On Tuesday, 17 August 2021 10:20:37 BST Robin Becker wrote: > While porting an ap from python2.7 to python3 I see this > > base64string = base64.b64encode('%s:%s' % (wsemail, wspassword)) > request.add_header("Authorization", "Basic %s" % base64string) > > in python3.x I find this works > > base64string = base64.b64encode(('%s:%s' % (wsemail, > wspassword)).encode('ascii')).decode('ascii') > request.add_header("Authorization", "Basic %s" % base64string) > > but I find the conversion to and from ascii irksome. Is there a more direct > way to create the basic auth value? base64 works on BYTES not UNICODE that is why you need to convert to BYTES. Its an important detail that you must handle. The py2 code meant that you only see errors if you have a value in your string that is outside the ASCII range. > As an additional issue I find I have no clear idea what encoding is allowed > for the components of a basic auth input. -- You will want to read this: https://datatracker.ietf.org/doc/html/rfc7617#section-2.1 It talks about a "charset" auth-param, then seems to say that only allowed value is utf-8 and you most have the unicode Normalization Form C ("NFC"). Oh and if you have the freedom avoid Basic Auth as its not secure at all. > Robin Becker Barry From rosuav at gmail.com Tue Aug 17 14:19:51 2021 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 18 Aug 2021 04:19:51 +1000 Subject: Cyclic imports In-Reply-To: <11811693.O9o76ZdvQC@varric.chelsea.private> References: <11811693.O9o76ZdvQC@varric.chelsea.private> Message-ID: On Wed, Aug 18, 2021 at 4:10 AM Barry Scott wrote: > > def allImports( self, module_name ): > for line in f: > words = line.strip().split() > if words[0:1] == ['import']: > all_imports.append( words[1] ) > This will work for a lot of programs, but it depends too much on coding style. If you feel like trying something a little more adventurous, I'd recommend looking into the ast module: >>> import ast >>> ast.parse(""" ... import foo ... import bar, baz ... from quux import spam ... try: import hello ... except ImportError: import goodbye ... """) >>> m = _ >>> ast.dump(m) "Module(body=[Import(names=[alias(name='foo')]), Import(names=[alias(name='bar'), alias(name='baz')]), ImportFrom(module='quux', names=[alias(name='spam')], level=0), Try(body=[Import(names=[alias(name='hello')])], handlers=[ExceptHandler(type=Name(id='ImportError', ctx=Load()), body=[Import(names=[alias(name='goodbye')])])], orelse=[], finalbody=[])], type_ignores=[])" If you ast.parse() the text of a Python script, you'll get a Module that has all the top-level code in a list. It's then up to you how much you dig into that. For instance, a simple try/except like this is fairly common, but if something's inside a FunctionDef, you might want to ignore it. Or maybe just ignore everything that isn't an Import or FromImport, which would be a lot easier, but would miss the try/except example. The main advantage of ast.parse() is that it no longer cares about code layout, and it won't be fooled by an import statement inside a docstring, or anything like that. It's also pretty easy to handle multiple variants (note how "import bar, baz" just has two things in the names list). ChrisA From rosuav at gmail.com Tue Aug 17 14:22:50 2021 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 18 Aug 2021 04:22:50 +1000 Subject: basic auth request In-Reply-To: <4647390.GXAFRqVoOG@varric.chelsea.private> References: <07b8928a-fe1f-958b-3ee2-d0f6ec51d414@everest.reportlab.co.uk> <4647390.GXAFRqVoOG@varric.chelsea.private> Message-ID: On Wed, Aug 18, 2021 at 4:16 AM Barry Scott wrote: > Oh and if you have the freedom avoid Basic Auth as its not secure at all. > That's usually irrelevant, since the alternative is most likely to be form fill-out, which is exactly as secure. If you're serving over HTTPS, the page is encrypted, and that includes the headers; if you're not, then it's not encrypted, and that includes the form body. There are other issues with basic auth, but security really isn't one. ChrisA From barry at barrys-emacs.org Tue Aug 17 17:15:09 2021 From: barry at barrys-emacs.org (Barry) Date: Tue, 17 Aug 2021 22:15:09 +0100 Subject: basic auth request In-Reply-To: References: Message-ID: <54465DA0-2977-4EAD-8CD2-C398F5ACF121@barrys-emacs.org> > On 17 Aug 2021, at 19:25, Chris Angelico wrote: > > ?On Wed, Aug 18, 2021 at 4:16 AM Barry Scott wrote: >> Oh and if you have the freedom avoid Basic Auth as its not secure at all. >> > > That's usually irrelevant, since the alternative is most likely to be > form fill-out, which is exactly as secure. If you're serving over > HTTPS, the page is encrypted, and that includes the headers; if you're > not, then it's not encrypted, and that includes the form body. There is digest and Ntlm that do not reveal the password. If you are over TLS then form or base is as good as each other. Barry > > There are other issues with basic auth, but security really isn't one. > > ChrisA > -- > https://mail.python.org/mailman/listinfo/python-list > From rosuav at gmail.com Tue Aug 17 17:18:28 2021 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 18 Aug 2021 07:18:28 +1000 Subject: basic auth request In-Reply-To: <54465DA0-2977-4EAD-8CD2-C398F5ACF121@barrys-emacs.org> References: <54465DA0-2977-4EAD-8CD2-C398F5ACF121@barrys-emacs.org> Message-ID: On Wed, Aug 18, 2021 at 7:15 AM Barry wrote: > > > > > On 17 Aug 2021, at 19:25, Chris Angelico wrote: > > > > ?On Wed, Aug 18, 2021 at 4:16 AM Barry Scott wrote: > >> Oh and if you have the freedom avoid Basic Auth as its not secure at all. > >> > > > > That's usually irrelevant, since the alternative is most likely to be > > form fill-out, which is exactly as secure. If you're serving over > > HTTPS, the page is encrypted, and that includes the headers; if you're > > not, then it's not encrypted, and that includes the form body. > > There is digest and Ntlm that do not reveal the password. > And they require that the password be stored decryptably on the server, which is a different vulnerability. It's all a matter of which threat is more serious to you. Fundamentally, basic auth is no better or worse than any of the other forms - it's just different. ChrisA From eryksun at gmail.com Tue Aug 17 18:23:19 2021 From: eryksun at gmail.com (Eryk Sun) Date: Tue, 17 Aug 2021 17:23:19 -0500 Subject: Regarding inability of Python Module Winsound to produce beep in decimal frequency In-Reply-To: References: <20210815130117.03c23726@e7240.home> <6068cc72-6377-458d-0bde-35919f327782@roelschroeven.net> Message-ID: On 8/17/21, Dennis Lee Bieber wrote: > On Tue, 17 Aug 2021 15:11:05 +1000, Chris Angelico > declaimed the following: > >>Huh. Okay. Then I withdraw the concern from this list, and instead lay >>it at Microsoft's feet. That is, I maintain, a bizarre choice. Surely >>there are better ways to trigger audio on the sound card? > > Possibly there is a section of code that determines if a sound card is > available, and if not, routes to the basic internal speaker. The rest of > the wave form logic is probably still of use for that. It may be that there's a fallback audio device that uses the PC speaker on systems that lack even basic audio support in their chipset. But in common practice, Beep() does not use the PC speaker. The "beep.sys" driver in Windows 7+ has no code path that starts a PC speaker beep via HalMakeBeep(frequency) and ends it after a timeout via HalMakeBeep(0), which was the old implementation of "beep.sys" that can still be seen in ReactOS [1]. The HAL (hardware abstraction layer) function HalMakeBeep() is still implemented in Windows 10, but without the connection to an IOCTL in "\Device\Beep", or some other installed device driver, there's no way for user-mode code to make a beep with the classic PC speaker. In Windows 7+, the beep device's IOCTL_BEEP_SET function is just a relay. It's implemented by searching for and completing a queued IOCTL request from a task in the user's session (i.e. an inverted callback from kernel mode to user mode). This task, which is scheduled to run at logon in every interactive session, executes the "PlaySoundSrv.dll" module in an instance of "taskhostw.exe". Upon completion of its queued IOCTL, from which it gets the beep frequency and duration, the sound server generates the requested beep waveform and plays it on the default audio output device via WinAPI PlaySound(). Notably, the "beep.sys" driver doesn't support manually starting the sound-server task in the user's session. So if one terminates the "taskhostw.exe" process that's hosting "PlaySoundSrv.dll", WinAPI Beep() will no longer work. To get it back, the "\Microsoft\Windows\Multimedia\SystemSoundsService" task has to be restarted manually. --- [1] https://github.com/reactos/reactos/blob/master/drivers/base/beep/beep.c#L295 From jon+usenet at unequivocal.eu Tue Aug 17 17:47:33 2021 From: jon+usenet at unequivocal.eu (Jon Ribbens) Date: Tue, 17 Aug 2021 21:47:33 -0000 (UTC) Subject: basic auth request References: <54465DA0-2977-4EAD-8CD2-C398F5ACF121@barrys-emacs.org> Message-ID: On 2021-08-17, Barry wrote: >> That's usually irrelevant, since the alternative is most likely to be >> form fill-out, which is exactly as secure. If you're serving over >> HTTPS, the page is encrypted, and that includes the headers; if you're >> not, then it's not encrypted, and that includes the form body. > > There is digest and Ntlm that do not reveal the password. That's only true if you're not using HTTPS - and you should *never* not be using HTTPS, and that goes double if forms are being filled in and double again if passwords are being supplied. From Gronicus at SGA.Ninja Wed Aug 18 00:43:32 2021 From: Gronicus at SGA.Ninja (Steve) Date: Wed, 18 Aug 2021 00:43:32 -0400 Subject: Regarding inability of Python Module Winsound to produce beep in decimal frequency In-Reply-To: References: <20210815130117.03c23726@e7240.home> <6068cc72-6377-458d-0bde-35919f327782@roelschroeven.net> Message-ID: <013d01d793eb$99ec8050$cdc580f0$@SGA.Ninja> "The HAL (hardware abstraction layer) function HalMakeBeep()" Is the beep that opens the pod bay doors? Footnote: ?George Melly remarked to Mike Jagger on how lined his face was for one so young. Jagger replied ?They?re laughter lines George? to which Melly countered: ?Mick, nothing?s that f**king funny!?. -----Original Message----- From: Python-list On Behalf Of Eryk Sun Sent: Tuesday, August 17, 2021 6:23 PM To: Dennis Lee Bieber Cc: python-list at python.org Subject: Re: Regarding inability of Python Module Winsound to produce beep in decimal frequency On 8/17/21, Dennis Lee Bieber wrote: > On Tue, 17 Aug 2021 15:11:05 +1000, Chris Angelico > declaimed the following: > >>Huh. Okay. Then I withdraw the concern from this list, and instead lay >>it at Microsoft's feet. That is, I maintain, a bizarre choice. Surely >>there are better ways to trigger audio on the sound card? > > Possibly there is a section of code that determines if a sound card > is available, and if not, routes to the basic internal speaker. The > rest of the wave form logic is probably still of use for that. It may be that there's a fallback audio device that uses the PC speaker on systems that lack even basic audio support in their chipset. But in common practice, Beep() does not use the PC speaker. The "beep.sys" driver in Windows 7+ has no code path that starts a PC speaker beep via HalMakeBeep(frequency) and ends it after a timeout via HalMakeBeep(0), which was the old implementation of "beep.sys" that can still be seen in ReactOS [1]. The HAL (hardware abstraction layer) function HalMakeBeep() is still implemented in Windows 10, but without the connection to an IOCTL in "\Device\Beep", or some other installed device driver, there's no way for user-mode code to make a beep with the classic PC speaker. In Windows 7+, the beep device's IOCTL_BEEP_SET function is just a relay. It's implemented by searching for and completing a queued IOCTL request from a task in the user's session (i.e. an inverted callback from kernel mode to user mode). This task, which is scheduled to run at logon in every interactive session, executes the "PlaySoundSrv.dll" module in an instance of "taskhostw.exe". Upon completion of its queued IOCTL, from which it gets the beep frequency and duration, the sound server generates the requested beep waveform and plays it on the default audio output device via WinAPI PlaySound(). Notably, the "beep.sys" driver doesn't support manually starting the sound-server task in the user's session. So if one terminates the "taskhostw.exe" process that's hosting "PlaySoundSrv.dll", WinAPI Beep() will no longer work. To get it back, the "\Microsoft\Windows\Multimedia\SystemSoundsService" task has to be restarted manually. --- [1] https://github.com/reactos/reactos/blob/master/drivers/base/beep/beep.c#L295 -- https://mail.python.org/mailman/listinfo/python-list From joepareti54 at gmail.com Wed Aug 18 11:59:56 2021 From: joepareti54 at gmail.com (joseph pareti) Date: Wed, 18 Aug 2021 17:59:56 +0200 Subject: question on trax In-Reply-To: References: Message-ID: yes, but I do not see Fn anywhere. Another question is on this line: z = add((x, y)) If I code: z = add(x, y) Then the following exception occurs : *Expected input to be a tuple or list; instead got .* Am Di., 17. Aug. 2021 um 19:21 Uhr schrieb MRAB : > On 2021-08-17 16:50, joseph pareti wrote: > > In the following code, where does tl.Fn come from? i see it nowhere in > the > > documents, i.e I was looking for trax.layers.Fn : > > > > import numpy as np > > *from trax import layers as tl* > > from trax import shapes > > from trax import fastmath > > # > > def Addition(): > > layer_name = "Addition" # don't forget to give your custom layer a > > name to identify > > > > # Custom function for the custom layer > > def func(x, y): > > return x + y > > > > return *tl.Fn*(layer_name, func) > > > [snip] > It comes from using the line: > > from trax import layers as tl > > so it's equivalent to 'trax.layers.Fn'. > -- > https://mail.python.org/mailman/listinfo/python-list > -- Regards, Joseph Pareti - Artificial Intelligence consultant Joseph Pareti's AI Consulting Services https://www.joepareti54-ai.com/ cell +49 1520 1600 209 cell +39 339 797 0644 From robin at reportlab.com Wed Aug 18 03:36:41 2021 From: robin at reportlab.com (Robin Becker) Date: Wed, 18 Aug 2021 08:36:41 +0100 Subject: basic auth request In-Reply-To: References: <54465DA0-2977-4EAD-8CD2-C398F5ACF121@barrys-emacs.org> Message-ID: <9bc605cb-2ceb-fed9-cd3f-d48a8fe405fb@everest.reportlab.co.uk> On 17/08/2021 22:47, Jon Ribbens via Python-list wrote: ....... > That's only true if you're not using HTTPS - and you should *never* > not be using HTTPS, and that goes double if forms are being filled > in and double again if passwords are being supplied. > I think I agree with most of the replies; I understood from reading the rfc that the charset is utf8 (presumably without ':') and that basic auth is considered insecure. It is being used over https so should avoid the simplest net scanning. I googled a bunch of ways to do this, but many come down to 1) using the requests package or 2) setting up an opener. Both of these seem to be much more complex than is required to add the header. I thought there might be a shortcut or more elegant way to replace the old code, but it seems not thanks -- Robin Becker From greg.ewing at canterbury.ac.nz Wed Aug 18 11:49:01 2021 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Thu, 19 Aug 2021 03:49:01 +1200 Subject: Regarding inability of Python Module Winsound to produce beep in decimal frequency In-Reply-To: References: <20210815130117.03c23726@e7240.home> <6068cc72-6377-458d-0bde-35919f327782@roelschroeven.net> <013d01d793eb$99ec8050$cdc580f0$@SGA.Ninja> Message-ID: On 18/08/21 4:43 pm, Steve wrote: > > "The HAL (hardware abstraction layer) function HalMakeBeep()" > Is the beep that opens the pod bay doors? def HalMakeBeepUsingPCSpeaker(): raise IOError("I'm sorry, I can't do that, Dave.") -- Greg From wlfraed at ix.netcom.com Wed Aug 18 12:42:59 2021 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Wed, 18 Aug 2021 12:42:59 -0400 Subject: question on trax References: Message-ID: On Tue, 17 Aug 2021 17:50:59 +0200, joseph pareti declaimed the following: >In the following code, where does tl.Fn come from? i see it nowhere in the >documents, i.e I was looking for trax.layers.Fn : "layers" imports a whole slew of sub modules using from xxx import * in order to put all the sub module names at the same level. https://github.com/google/trax/blob/master/trax/layers/base.py >From line 748 on... def Fn(name, f, n_out=1): # pylint: disable=invalid-name """Returns a layer with no weights that applies the function `f`. `f` can take and return any number of arguments, and takes only positional arguments -- no default or keyword arguments. It often uses JAX-numpy (`jnp`). The following, for example, would create a layer that takes two inputs and returns two outputs -- element-wise sums and maxima: `Fn('SumAndMax', lambda x0, x1: (x0 + x1, jnp.maximum(x0, x1)), n_out=2)` The layer's number of inputs (`n_in`) is automatically set to number of positional arguments in `f`, but you must explicitly set the number of outputs (`n_out`) whenever it's not the default value 1. Args: name: Class-like name for the resulting layer; for use in debugging. f: Pure function from input tensors to output tensors, where each input tensor is a separate positional arg, e.g., `f(x0, x1) --> x0 + x1`. Output tensors must be packaged as specified in the `Layer` class docstring. n_out: Number of outputs promised by the layer; default value 1. Returns: Layer executing the function `f`. """ -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From Gronicus at SGA.Ninja Wed Aug 18 14:36:29 2021 From: Gronicus at SGA.Ninja (Steve) Date: Wed, 18 Aug 2021 14:36:29 -0400 Subject: Regarding inability of Python Module Winsound to produce beep in decimal frequency In-Reply-To: References: <20210815130117.03c23726@e7240.home> <6068cc72-6377-458d-0bde-35919f327782@roelschroeven.net> <013d01d793eb$99ec8050$cdc580f0$@SGA.Ninja> Message-ID: <01bd01d7945f$f71aed60$e550c820$@SGA.Ninja> -----Original Message----- From: Python-list On Behalf Of Greg Ewing Sent: Wednesday, August 18, 2021 11:49 AM To: python-list at python.org Subject: Re: Regarding inability of Python Module Winsound to produce beep in decimal frequency On 18/08/21 4:43 pm, Steve wrote: >> >> "The HAL (hardware abstraction layer) function HalMakeBeep()" >> Is the beep that opens the pod bay doors? > def HalMakeBeepUsingPCSpeaker(): > raise IOError("I'm sorry, I can't do that, Dave.") I tried that but all it reported was a very slow: "Daisy, Daisy, give me your answer dooooo...." And that is when I figured that I knew I should have done that backup.... From brunobrlirio at gmail.com Wed Aug 18 15:57:06 2021 From: brunobrlirio at gmail.com (Bruno Lirio) Date: Wed, 18 Aug 2021 12:57:06 -0700 (PDT) Subject: Compute working days In-Reply-To: <61bd7316-a3a5-40a7-a27b-4c74cda1a819@c11g2000yqj.googlegroups.com> References: <61bd7316-a3a5-40a7-a27b-4c74cda1a819@c11g2000yqj.googlegroups.com> Message-ID: <89bfa317-950a-46b7-b5b9-ec855329dbc4n@googlegroups.com> Em s?bado, 14 de mar?o de 2009 ?s 13:59:41 UTC-3, Casey escreveu: > How about: > from datetime import date, timedelta > # Define the weekday mnemonics to match the date.weekday function > (MON, TUE, WED, THU, FRI, SAT, SUN) = range(7) > def workdays(start_date, end_date, whichdays=(MON,TUE,WED,THU,FRI)): > ''' > Calculate the number of working days between two dates inclusive > (start_date <= end_date). > The actual working days can be set with the optional whichdays > parameter > (default is MON-FRI) > ''' > delta_days = (end_date - start_date).days + 1 > full_weeks, extra_days = divmod(delta_days, 7) > # num_workdays = how many days/week you work * total # of weeks > num_workdays = (full_weeks + 1) * len(whichdays) > # subtract out any working days that fall in the 'shortened week' > for d in range(1, 8 - extra_days): > if (end_date + timedelta(d)).weekday() in whichdays: > num_workdays -= 1 > return num_workdays Could it include the holidays in Brazil? From python at mrabarnett.plus.com Wed Aug 18 18:33:02 2021 From: python at mrabarnett.plus.com (MRAB) Date: Wed, 18 Aug 2021 23:33:02 +0100 Subject: Compute working days In-Reply-To: <89bfa317-950a-46b7-b5b9-ec855329dbc4n@googlegroups.com> References: <61bd7316-a3a5-40a7-a27b-4c74cda1a819@c11g2000yqj.googlegroups.com> <89bfa317-950a-46b7-b5b9-ec855329dbc4n@googlegroups.com> Message-ID: On 2021-08-18 20:57, Bruno Lirio wrote: > Em s?bado, 14 de mar?o de 2009 ?s 13:59:41 UTC-3, Casey escreveu: >> How about: >> from datetime import date, timedelta >> # Define the weekday mnemonics to match the date.weekday function >> (MON, TUE, WED, THU, FRI, SAT, SUN) = range(7) >> def workdays(start_date, end_date, whichdays=(MON,TUE,WED,THU,FRI)): >> ''' >> Calculate the number of working days between two dates inclusive >> (start_date <= end_date). >> The actual working days can be set with the optional whichdays >> parameter >> (default is MON-FRI) >> ''' >> delta_days = (end_date - start_date).days + 1 >> full_weeks, extra_days = divmod(delta_days, 7) >> # num_workdays = how many days/week you work * total # of weeks >> num_workdays = (full_weeks + 1) * len(whichdays) >> # subtract out any working days that fall in the 'shortened week' >> for d in range(1, 8 - extra_days): >> if (end_date + timedelta(d)).weekday() in whichdays: >> num_workdays -= 1 >> return num_workdays > Could it include the holidays in Brazil? > Yes. The algorithms calculates the number of working days, assuming no holidays, so you'd then subtract any working days between the start and end dates that are actually holidays. From jon+usenet at unequivocal.eu Wed Aug 18 19:05:46 2021 From: jon+usenet at unequivocal.eu (Jon Ribbens) Date: Wed, 18 Aug 2021 23:05:46 -0000 (UTC) Subject: basic auth request References: <54465DA0-2977-4EAD-8CD2-C398F5ACF121@barrys-emacs.org> <9bc605cb-2ceb-fed9-cd3f-d48a8fe405fb@everest.reportlab.co.uk> Message-ID: On 2021-08-18, Robin Becker wrote: > On 17/08/2021 22:47, Jon Ribbens via Python-list wrote: > ....... >> That's only true if you're not using HTTPS - and you should *never* >> not be using HTTPS, and that goes double if forms are being filled >> in and double again if passwords are being supplied. > > I think I agree with most of the replies; I understood from reading > the rfc that the charset is utf8 (presumably without ':') The username can't contain a ':'. It shouldn't matter in the password. > and that basic auth is considered insecure. It is being used over > https so should avoid the simplest net scanning. It's not insecure over HTTPS. Bear in mind the Basic Auth RFC was written when HTTP was the standard and HTTPS was unusual. The positions are now effectively reversed. > I googled a bunch of ways to do this, but many come down to 1) using > the requests package or 2) setting up an opener. Both of these seem to > be much more complex than is required to add the header. > > I thought there might be a shortcut or more elegant way to replace the > old code, but it seems not It's only a trivial str/bytes difference, it shouldn't be any big deal. But using 'requests' instead is likely to simplify things and doesn't tend to be an onerous dependency. From greg.ewing at canterbury.ac.nz Wed Aug 18 20:35:49 2021 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Thu, 19 Aug 2021 12:35:49 +1200 Subject: question on trax In-Reply-To: References: Message-ID: On 19/08/21 3:59 am, joseph pareti wrote: > Another question is on this line: > z = add((x, y)) > If I code: > z = add(x, y) > Then the following exception occurs : > > *Expected input to be a tuple or list; instead got .* What exactly is your question? Does add((x, y)) not do what you want? If not, you'll have to tell us what you do want. -- Greg From shariesk at sundaelectronics.com Wed Aug 18 21:52:35 2021 From: shariesk at sundaelectronics.com (Shari Eskenas) Date: Wed, 18 Aug 2021 18:52:35 -0700 (PDT) Subject: Upcoming book: Learn Python through Nursery Rhymes and Fairy Tales Message-ID: <3f7a73db-0e39-4a16-8bd4-77d648cd855en@googlegroups.com> Hi everyone, I'm writing a new Python book for beginners called Learn Python through Nursery Rhymes and Fairy Tales. It teaches Python concepts by translating the classic tales into Python programs. I launched the book on Kickstarter for pre-order- you can check it out here: https://www.kickstarter.com/projects/914595512/learn-python-through-nursery-rhymes-and-fairy-tales I'd be happy to hear any questions or comments you have. Thank you, Shari From robin at reportlab.com Thu Aug 19 09:07:43 2021 From: robin at reportlab.com (Robin Becker) Date: Thu, 19 Aug 2021 14:07:43 +0100 Subject: what to do with multiple BOMs In-Reply-To: References: <61bd7316-a3a5-40a7-a27b-4c74cda1a819@c11g2000yqj.googlegroups.com> <89bfa317-950a-46b7-b5b9-ec855329dbc4n@googlegroups.com> Message-ID: Channeling unicode text experts and xml people: I have xml entity with initial bytes ff fe ff fe which the file command says is UTF-16, little-endian text. I agree, but what should be done about the additional BOM. A test output made many years ago seems to keep the extra BOM. The xml context is xml file 014.xml ]> &e;\xef\xbb\xbfdata' which implies seems as though the extra BOM in the entity has been kept and processed into a different BOM meaning utf8. I think the test file is wrong and that multiple BOM chars in the entiry should have been removed. Am I right? -- Robin Becker From hrouselle at jevedi.com Thu Aug 19 13:32:57 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Thu, 19 Aug 2021 14:32:57 -0300 Subject: on perhaps unloading modules? References: <86pmueu8a5.fsf@jevedi.com> Message-ID: <861r6pgx12.fsf@jevedi.com> Chris Angelico writes: > On Tue, Aug 17, 2021 at 4:02 AM Greg Ewing > wrote: >> The second best way would be to not use import_module, but to >> exec() the student's code. That way you don't create an entry in >> sys.modules and don't have to worry about somehow unloading the >> module. > > I would agree with this. If you need to mess around with modules and > you don't want them to be cached, avoid the normal "import" mechanism, > and just exec yourself a module's worth of code. Sounds like a plan. Busy, haven't been able to try it out. But I will. Soon. Thank you! From hrouselle at jevedi.com Thu Aug 19 13:38:59 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Thu, 19 Aug 2021 14:38:59 -0300 Subject: on perhaps unloading modules? References: <86pmueu8a5.fsf@jevedi.com> <86tujqsq0p.fsf@jevedi.com> <20210817134116.r5gec64gkb53fdma@gmail.com> Message-ID: <86sfz5fi6k.fsf@jevedi.com> Martin Di Paola writes: > This may not answer your question but it may provide an alternative > solution. > > I had the same challenge that you an year ago so may be my solution will > work for you too. > > Imagine that you have a Markdown file that *documents* the expected > results. > > This is the final exam, good luck! > > First I'm going to load your code (the student's code): > > ```python >>>> import student > ``` > > Let's see if you programmed correctly a sort algorithm > > ```python >>>> data = [3, 2, 1, 3, 1, 9] >>>> student.sort_numbers(data) > [1, 1, 2, 3, 3, 9] > ``` > > Let's now if you can choose the correct answer: > > ```python >>>> t = ["foo", "bar", "baz"] >>>> student.question1(t) > "baz" > ``` > > Now you can run the snippets of code with: > > byexample -l python the_markdown_file.md > > What byexample does is to run the Python code, capture the output and > compare it with the expected result. > > In the above example "student.sort_numbers" must return the list > sorted. > That output is compared by byexample with the list written below. > > Advantages? Each byexample run is independent of the other and the > snippet of codes are executed in a separated Python process. byexample > takes care of the IPC. > > I don't know the details of your questions so I'm not sure if byexample > will be the tool for you. In my case I evaluate my students giving them > the Markdown and asking them to code the functions so they return the > expected values. Currently procedures in one question are used in another question. Nevertheless, perhaps I could (in other tests) design something different. Although, to be honest, I would rather not have to use something like Markdown because that means more syntax for students. > Depending of how many students you have you may considere to > complement this with INGInious. It is designed to run students' > assignments assuming nothing on the untrusted code. > > Links: > > https://byexamples.github.io/byexample/ > https://docs.inginious.org/en/v0.7/ INGInious looks pretty interesting. Thank you! From hrouselle at jevedi.com Thu Aug 19 13:47:08 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Thu, 19 Aug 2021 14:47:08 -0300 Subject: some problems for an introductory python test References: <868s1acoo1.fsf@jevedi.xotimo> <9e930795-7664-4e75-48b6-afa03c666e48@wichmann.us> <86lf599zse.fsf@jevedi.xotimo> <868s18b1p7.fsf@jevedi.com> <868s16zol5.fsf@jevedi.com> <86sfzbwdyl.fsf@jevedi.com> Message-ID: <86eeapfhsz.fsf@jevedi.com> Chris Angelico writes: > On Tue, Aug 17, 2021 at 3:51 AM Hope Rouselle > wrote: >> >> Chris Angelico writes: >> >> Wow, I kinda feel the same as you here. I think this justifies >> >> perhaps >> >> using a hardware solution. (Crazy idea?! Lol.) >> > >> > uhhh........ Yes. Very crazy idea. Can't imagine why anyone would >> > ever >> > think about doing that. >> >> Lol. Really? I mean a certain panic button. You know the GNU Emacs. >> It has this queue with the implications you mentioned --- as much as it >> can. (It must of course get the messages from the system, otherwise it >> can't do anything about it.) And it has the panic button C-g. The >> keyboard has one the highest precedences in hardware interrupts, >> doesn't >> it not? A certain very important system could have a panic button that >> invokes a certain debugger, say, for a crisis-moment. >> >> But then this could be a lousy engineering strategy. I am not an >> expert >> at all in any of this. But I'm surprised with your quick >> dismissal. :-) >> >> > Certainly nobody in his right mind would have WatchCat listening on >> > the serial port's Ring Indicator interrupt, and then grab a paperclip >> > to bridge the DTR and RI pins on an otherwise-unoccupied serial port >> > on the back of the PC. (The DTR pin was kept high by the PC, and >> > could >> > therefore be used as an open power pin to bring the RI high.) >> >> Why not? Misuse of hardware? Too precious of a resource? >> >> > If you're curious, it's pins 4 and 9 - diagonally up and in from the >> > short >> > corner. http://www.usconverters.com/index.php?main_page=page&id=61&chapter=0 >> >> You know your pins! That's impressive. I thought the OS itself could >> use something like that. The fact that they never do... Says >> something, >> doesn't it? But it's not too obvious to me. >> >> > And of COURSE nobody would ever take an old serial mouse, take the >> > ball out of it, and turn it into a foot-controlled signal... although >> > that wasn't for WatchCat, that was for clipboard management >> > between my >> > app and a Windows accounting package that we used. But that's a >> > separate story. >> >> Lol. I feel you're saying you would. :-) > > This was all a figure of speech, and the denials were all tongue in > cheek. Not only am I saying we would, but we *did*. All of the above. Cool! :-) > The Ring Indicator trick was one of the best, since we had very little > other use for serial ports, and it didn't significantly impact the > system during good times, but was always reliable when things went > wrong. > > (And when I posted it, I could visualize the port and knew which pins > to bridge, but had to go look up a pinout to be able to say their pin > numbers and descriptions.) Nice! >> I heard of Python for the first time in the 90s. I worked at an ISP. >> Only one guy was really programming there, Allaire ColdFusion. But, >> odd enough, we used to say we would ``write a script in Python'' when >> we meant to say we were going out for a smoke. I think that was >> precisely because nobody knew that ``Python'' really was. I never >> expected it to be a great language. I imagined it was something like >> Tcl. (Lol, no offense at all towards Tcl.) > > Haha, that's a weird idiom! Clueless people --- from Rio de Janeiro area in Brazil. :-) It was effectively just an in-joke. > Funny you should mention Tcl. > > https://docs.python.org/3/library/tkinter.html Cool! Speaking of GUIs and Python, that Google software called Backup and Sync (which I think it's about to be obsoleted by Google Drive) is written in Python --- it feels a bit heavy. The GUI too seems a bit slow sometimes. Haven't tried their ``Google Drive'' as a replacement yet. From python at mrabarnett.plus.com Thu Aug 19 14:52:35 2021 From: python at mrabarnett.plus.com (MRAB) Date: Thu, 19 Aug 2021 19:52:35 +0100 Subject: what to do with multiple BOMs In-Reply-To: References: <61bd7316-a3a5-40a7-a27b-4c74cda1a819@c11g2000yqj.googlegroups.com> <89bfa317-950a-46b7-b5b9-ec855329dbc4n@googlegroups.com> Message-ID: On 2021-08-19 14:07, Robin Becker wrote: > Channeling unicode text experts and xml people: > > I have xml entity with initial bytes ff fe ff fe which the file command says is > UTF-16, little-endian text. > > I agree, but what should be done about the additional BOM. > > A test output made many years ago seems to keep the extra BOM. The xml context is > > > xml file 014.xml > > > ]> > &e; > the entitity file 014.ent is bombomdata > > b'\xff\xfe\xff\xfed\x00a\x00t\x00a\x00' > > The old saved test output of processing is > > b'\xef\xbb\xbfdata' > > which implies seems as though the extra BOM in the entity has been kept and processed into a different BOM meaning utf8. > > I think the test file is wrong and that multiple BOM chars in the entiry should have been removed. > > Am I right? > The use of a BOM b'\xef\xbb\xbf' at the start of a UTF-8 file is a Windows thing. It's not used on non-Windows systems. Putting it in the middle, e.g. b'\xef\xbb\xbfdata', just looks wrong. It looks like the contents of a UTF-8 file, with a BOM because it originated on a Windows system, were read in without stripping the BOM first. From Richard at damon-family.org Thu Aug 19 14:55:49 2021 From: Richard at damon-family.org (Richard Damon) Date: Thu, 19 Aug 2021 14:55:49 -0400 Subject: what to do with multiple BOMs In-Reply-To: References: Message-ID: <51160E02-F5B1-48F9-B499-5D2D8C737E5F@damon-family.org> By the rules of Unicode, that character, if not the very first character of the file, should be treated as a ?zero-width non-breaking space?, it is NOT a BOM character there. It?s presence in the files is almost certainly an error, and being caused by broken software or software processing files in a manner that it wasn?t designed for. > On Aug 19, 2021, at 1:48 PM, Robin Becker wrote: > > ?Channeling unicode text experts and xml people: > > I have xml entity with initial bytes ff fe ff fe which the file command says is > UTF-16, little-endian text. > > I agree, but what should be done about the additional BOM. > > A test output made many years ago seems to keep the extra BOM. The xml context is > > > xml file 014.xml > > > ]> > &e; > the entitity file 014.ent is bombomdata > > b'\xff\xfe\xff\xfed\x00a\x00t\x00a\x00' > > The old saved test output of processing is > > b'\xef\xbb\xbfdata' > > which implies seems as though the extra BOM in the entity has been kept and processed into a different BOM meaning utf8. > > I think the test file is wrong and that multiple BOM chars in the entiry should have been removed. > > Am I right? > -- > Robin Becker > > -- > https://mail.python.org/mailman/listinfo/python-list From janburse at fastmail.fm Thu Aug 19 17:36:36 2021 From: janburse at fastmail.fm (Mostowski Collapse) Date: Thu, 19 Aug 2021 23:36:36 +0200 Subject: ANN: Dogelog Runtime, Prolog to the Moon (2021) In-Reply-To: References: Message-ID: Woa! The JavaScript JIT compiler is quite impressive. I now ported Dogelog runtime to Python as well, so that I can compare JavaScript and Python, and tested without clause indexing: between(L,H,L) :- L =< H. between(L,H,X) :- L < H, Y is L+1, between(Y,H,X). setup :- between(1,255,N), M is N//2, assertz(edge(M,N)), fail. setup :- edge(M,N), assertz(edge2(N,M)), fail. setup. anc(X,Y) :- edge(X, Y). anc(X,Y) :- edge(X, Z), anc(Z, Y). anc2(X,Y) :- edge2(Y, X). anc2(X,Y) :- edge2(Y, Z), anc2(X, Z). :- setup. :- time((between(1,10,_), anc2(0,255), fail; true)). :- time((between(1,10,_), anc(0,255), fail; true)). The results are: /* Python 3.10.0rc1 */ % Wall 188 ms, trim 0 ms % Wall 5537 ms, trim 0 ms /* JavaScript Chrome 92.0.4515.159 */ % Wall 5 ms, trim 0 ms % Wall 147 ms, trim 0 ms From janburse at fastmail.fm Thu Aug 19 17:37:03 2021 From: janburse at fastmail.fm (Mostowski Collapse) Date: Thu, 19 Aug 2021 23:37:03 +0200 Subject: ANN: Dogelog Runtime, Prolog to the Moon (2021) In-Reply-To: References: Message-ID: Thats a factor 37.8 faster! I tested the a variant of the Albufeira instructions Prolog VM aka ZIP, which was also the inspiration for SWI-Prolog. Open Source: The Python Version of the Dogelog Runtime https://github.com/jburse/dogelog-moon/tree/main/devel/runtimepy The Python Test Harness https://gist.github.com/jburse/bf6c01c7524f2611d606cb88983da9d6#file-test-py Mostowski Collapse schrieb: > Woa! The JavaScript JIT compiler is quite impressive. I now > ported Dogelog runtime to Python as well, so that I can compare > JavaScript and Python, and tested without clause indexing: > > between(L,H,L) :- L =< H. > between(L,H,X) :- L < H, Y is L+1, between(Y,H,X). > > setup :- between(1,255,N), M is N//2, assertz(edge(M,N)), fail. > setup :- edge(M,N), assertz(edge2(N,M)), fail. > setup. > > anc(X,Y) :- edge(X, Y). > anc(X,Y) :- edge(X, Z), anc(Z, Y). > > anc2(X,Y) :- edge2(Y, X). > anc2(X,Y) :- edge2(Y, Z), anc2(X, Z). > > :- setup. > :- time((between(1,10,_), anc2(0,255), fail; true)). > :- time((between(1,10,_), anc(0,255), fail; true)). > > The results are: > > /* Python 3.10.0rc1 */ > % Wall 188 ms, trim 0 ms > % Wall 5537 ms, trim 0 ms > > /* JavaScript Chrome 92.0.4515.159 */ > % Wall 5 ms, trim 0 ms > % Wall 147 ms, trim 0 ms From loris.bennett at fu-berlin.de Fri Aug 20 05:53:41 2021 From: loris.bennett at fu-berlin.de (Loris Bennett) Date: Fri, 20 Aug 2021 11:53:41 +0200 Subject: Making command-line args available to deeply-nested functions Message-ID: <87czq8tpay.fsf@hornfels.zedat.fu-berlin.de> Hi, TL;DR: If I have a command-line argument for a program, what is the best way of making this available to a deeply-nested[1] function call without passing the parameter through every intermediate function? Long version: If I have, say, a command-line program to send an email with a personalised salutation, a naive approach to the function calls might look like the following create_email(..., args.salutation_server_credentials) create_body(..., args.salutation_server_credentials) create_salutation(..., args.salutation_server_credentials) where args.salutation_server_credentials could be given on the command-line or read from a configuration file by the top-level, but is only ever actually needed by the create_salutation function. I can see that the top-level could just create an object from a class which encapsulates everything, but what if I want to keep the salutation generation separate, so that I can have a separate program which just generates the salutation and print it to the terminal? I guess I am really asking how to avoid "passing through" arguments to functions which only need them to call other functions, so maybe the answer is just to avoid nesting. Cheers, Loris Footnotes: [1] Is a TL;DR allowed to have footnotes? Probably not, but just to clarify, I would consider the third of three levels as being already "deeply-nested". -- This signature is currently under construction. From mutazilah at gmail.com Fri Aug 20 06:35:43 2021 From: mutazilah at gmail.com (Paul Edwards) Date: Fri, 20 Aug 2021 03:35:43 -0700 (PDT) Subject: port to PDOS (especially mainframe) In-Reply-To: <15731cd1-0dc1-4526-8783-1e4812d281fcn@googlegroups.com> References: <04534e58-4375-403b-980b-f44c062ce282n@googlegroups.com> <15731cd1-0dc1-4526-8783-1e4812d281fcn@googlegroups.com> Message-ID: On Saturday, April 17, 2021 at 11:12:38 PM UTC+10, Paul Edwards wrote: > https://github.com/s390guy/SATK/commits/master/README > > and I can see that on 2014-08-13 he cited 3.3 as an > explicit requirement. Note that the work I was doing to make a C90-compliant version of Python 3.3 hasn't progressed since late June 2021. You can see my work to date in python*.zip in custom.zip at http://pdos.org C:\devel\python\Modules>pdmake -f makefile.w32 BFN. Paul. From loris.bennett at fu-berlin.de Fri Aug 20 07:15:00 2021 From: loris.bennett at fu-berlin.de (Loris Bennett) Date: Fri, 20 Aug 2021 13:15:00 +0200 Subject: Making command-line args available to deeply-nested functions References: <87czq8tpay.fsf@hornfels.zedat.fu-berlin.de> <230149ee-f6ed-4e2f-8ac3-c12388ca45acn@googlegroups.com> Message-ID: <878s0wtljf.fsf@hornfels.zedat.fu-berlin.de> Julio Di Egidio writes: > On Friday, 20 August 2021 at 11:54:00 UTC+2, Loris Bennett wrote: >> Hi, >> >> TL;DR: >> >> If I have a command-line argument for a program, what is the best way >> of making this available to a deeply-nested[1] function call without >> passing the parameter through every intermediate function? > > To not pass arguments you need shared state ("global variables"): and > options in shard state, unless you have very good reasons to do > otherwise, is simply a no no. Doesn't that slightly depend on the size of your "globe"? If a program does a few, in some sense unrelated things, and, say, only runs for a few minutes, could you not decide to make a particular parameter global, even though only one function needs it? In general, however, I would also avoid this. > >> I can see that the top-level could just create an object from a class >> which encapsulates everything, but what if I want to keep the salutation >> generation separate, so that I can have a separate program which just >> generates the salutation and print it to the terminal? > > Yes, that's basically the way to go: parse arguments into a structure (an > object) that contains all options/parameters then pass that down. Next level: > some sections of your code may require a certain subset of those options, some > may require some other, so you would structure your options object in > sub-objects for the various sets of correlated options, then rather pass just > the sub-object(s) that are relevant to the section of code you are calling. > Variations are of course possible, anyway that's the basic idea. > > Also have a look at the "argparse" library, it does all the heavy lifting for > the parsing and creation of those objects, definitely advised for in non trivial > cases: . I am already using 'argparse' ('configargparse' actually). What aspect should I be looking at in order to produce "sub-objects"? >> I guess I am really asking how to avoid "passing through" arguments to >> functions which only need them to call other functions, so maybe the >> answer is just to avoid nesting. > > No, you don't get rid of code structure just not to pass arguments to > a function... Code may be poorly structured, but that's another > story. As I am writing new code it is more a question of imposing structure, rather than getting rid of structure. Unwritten code for a given purpose obviously has some sort of structure with regards to, say, loops and conditions, but I am less sure about the implications for how the code should be nested. Another argument against deeply-nested functions is the increased complexity of testing. Cheers, Loris -- This signature is currently under construction. From hrouselle at jevedi.com Fri Aug 20 13:29:05 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Fri, 20 Aug 2021 14:29:05 -0300 Subject: some problems for an introductory python test References: <86lf599zse.fsf@jevedi.xotimo> <868s18b1p7.fsf@jevedi.com> <86o89zz9ch.fsf@jevedi.com> Message-ID: <861r6oja8u.fsf@jevedi.com> Dennis Lee Bieber writes: > On Sun, 15 Aug 2021 00:15:58 -0300, Hope Rouselle > declaimed the following: > > Giganews seems to have just vomited up three days worth of traffic... > >>Dennis Lee Bieber writes: >> >>> >>> Granted, the fact that the Amiga used a shared common address space for >>> all running applications made IPC quite easy -- one looked up the >>> application message port, then added a small packet to the linked list >>> associated with the port. That small packet basically held the address of >>> the message port for returning data, and the address of the data being >>> passed. The closet thing I've seen to that capability on systems with >>> process-isolated virtual memory is (Open)VMS "mailbox" structures. The >>> difference being that the entire data had to be written (QIO) to the >>> mailbox, and the receiver had to read (another QIO call) the message -- >>> this allowed the address space to change. >>> >>> I've not seen anything equivalent in my light perusal of the Win32 API >>> (the various guide books aren't layed out in any way to be a reference), >>> and Linux seems to use UNIX sockets for IPC... No way to search for a >>> connection point by name... >> >>I don't know anything about Amiga, REXX et cetera, so I might be totall >>off here. But since you spoke of your perusal of the Win32 API, let me >>add a tiny bit. I gave myself a quick tour through the Win32 API using >>Pavel Yosifovich's book ``Windows 10 System Programming''. It's a two >>volume work. The thing that impressed me the most was the many ways to >>do the IPC. The purpose the work is clearly to show what is available >>and it it probably does the job well. (I ignored Windows for most of my >>life and now I decided to take a look at it. I don't feel it has much >>of the elegance of UNIX. It's what it is.) > > For a book that was published only a year ago -- it seems to be hard to > find... Amazon has v1, but not v2. Indeed. I believe it's because it's not quite released yet. I had found it here: https://leanpub.com/windows10systemprogrammingpart2 And this seems to be a sort-of-early-release. I'm not really sure. > I have the "Windows Internals 6th" both volumes. > > The closet those get to IPC is something called ALPC -- and that is > declared to be internal only, not available to third party programmers. > > "Programming Windows 6th" is focused on using C# (which, for the most > part, means using the "managed" API, not the Win32 API directly). Makes sense. > "Mailslots" (I'm using Google to find Windows IPC options) initially > sound close to Amiga message ports... Except there is no status return > inherent to the system; Amiga messages contain a return address so a > program can wait for the status of processing by the destination address. > They also don't qualify as VMS mailboxes as there can only be one reader > (the creator of the mailslot). VMS mailboxes allow multiple writers and/or > multiple readers. > > "File mapping" doesn't provide any form of queuing -- multiple > "writers" would require manually implementing some protocol to track "next > available space" in the mapped file. It would allow bidirectional message > passing, but again that requires some rather nasty overhead information > (when is the return status valid -- it is presumed the client wanting the > return status would get it from the same memory space as the message it > sent, and that space can't be reused until the client explicitly frees it > -- again by some overhead protocol changing headers of free space. > > "Data Copy" also sounds close to Amiga message ports (closer than > "Mailslots"), but the online documentation doesn't indicate if it queues > messages. The documentation doesn't illustrate HOW to return TRUE or FALSE > (processed/rejected). It advices that the receiver should treat the data as > read-only -- though I have to wonder if it /could/ write a return status > into the same message structure before "returning TRUE". > > Named Pipes and Sockets both have the "tied to endpoints" problem, and > in the case of Pipes, may only allow one sender to connect at a time > (sockets are also one connection, but normally the receivers spawns a > thread for each active connection and the connections are made using > different allocated sockets). Thanks for these summaries! From hrouselle at jevedi.com Fri Aug 20 13:33:09 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Fri, 20 Aug 2021 14:33:09 -0300 Subject: on slices, negative indices, which are the equivalent procedures? References: <86sfznhk1f.fsf@example.com> <86wnos9ge8.fsf@jevedi.com> <4vi8hg1tfcd2vsrchgpnbpf9a9l7acf7rl@4ax.com> <86a6lj1k7a.fsf@jevedi.com> Message-ID: <86tujkhvhm.fsf@jevedi.com> Dennis Lee Bieber writes: > On Sun, 15 Aug 2021 00:05:29 -0300, Jack Brandom > declaimed the following: > >>Dennis Lee Bieber writes: >> > >>> subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] >>> sliceop: ':' [test] > >> >>This is looking less readable, so, no, I prefer that previous, which was >>much clearer about slices. I can't even quite make the slices out in >>these rules. (But thanks for the opportunity to try.) > > The last part of "subscript" has the main "slice" notation (stripping > the quotes) > > [test] : [test] > > and the "stride" component is [sliceop] being > > : [test] Let's see. Let ``-->'' mean ``expands to''. Then subscript --> [test] ':' [test] [sliceop] --> [test] ':' [test] ':' [test] Does the brackets mean that its content count be omitted? From hrouselle at jevedi.com Fri Aug 20 14:15:45 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Fri, 20 Aug 2021 15:15:45 -0300 Subject: on perhaps unloading modules? References: <86pmueu8a5.fsf@jevedi.com> Message-ID: <86k0kghtim.fsf@jevedi.com> Chris Angelico writes: > On Tue, Aug 17, 2021 at 4:02 AM Greg Ewing wrote: >> The second best way would be to not use import_module, but to >> exec() the student's code. That way you don't create an entry in >> sys.modules and don't have to worry about somehow unloading the >> module. > > I would agree with this. If you need to mess around with modules and > you don't want them to be cached, avoid the normal "import" mechanism, > and just exec yourself a module's worth of code. This is looks very interesting. --8<---------------cut here---------------start------------->8--- Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:01:18) [MSC v.1900 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> >>> code >>> code() 'def p():\n import math\n return math.e\n' >>> p Traceback (most recent call last): File "", line 1, in NameError: name 'p' is not defined >>> exec(code()) >>> p >>> p() 2.718281828459045 --8<---------------cut here---------------end--------------->8--- This is also totally unsafe, right? But at least it won't give me those loading problems I had before. But I think I'm gonna go with Greg Ewing's first option --- running it all on a separate process, computing that report I was computing, then printing it out to the stdout and reading it from a controller process to know the student's results. This way I'm one step closer to safety --- I could chroot it and give it a limited period of time for execution. I suppose I could also customize Python's environment to only allow the modules I'd like to allow as well as the builtins I'd like to allow. (That would be interesting as well.) So, alright, let me learn how to spawn a process. Thanks very much. From janburse at fastmail.fm Fri Aug 20 19:13:26 2021 From: janburse at fastmail.fm (Mostowski Collapse) Date: Sat, 21 Aug 2021 01:13:26 +0200 Subject: ANN: Dogelog Runtime, Prolog to the Moon (2021) In-Reply-To: References: Message-ID: We = Me and my cat named socrates The cat is a very good programmer: def meow(): print("meow meow, Prolog is not only SWI-Prolog") Julio Di Egidio schrieb: > On Sunday, 15 August 2021 at 14:43:42 UTC+2, Mostowski Collapse wrote: > >> Yesterday we went into a little programming binge > > Who is this "we"? > >> See also: >> >> Python Version of Dogelog Runtime special >> https://twitter.com/dogelogch/status/1426884473988292617 >> >> Python Version of Dogelog Runtime special >> https://www.facebook.com/groups/dogelog > > I haven't tried either but, assuming the code works ;), great stuff man. > > You might be the one(s) who save Prolog from oblivion... > > Julio > From greg.ewing at canterbury.ac.nz Fri Aug 20 20:06:23 2021 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Sat, 21 Aug 2021 12:06:23 +1200 Subject: on perhaps unloading modules? In-Reply-To: <86k0kghtim.fsf@jevedi.com> References: <86pmueu8a5.fsf@jevedi.com> <86k0kghtim.fsf@jevedi.com> Message-ID: On 21/08/21 6:15 am, Hope Rouselle wrote: >>>> code() > 'def p():\n import math\n return math.e\n' >>>> exec(code()) >>>> p > >>>> p() > 2.718281828459045 Note that this pollutes the globals of the module that you're calling exec() from. For better isolation you can pass in an explicit globals dict: g = {} exec(code(), g) g['p']() -- Greg From hrouselle at jevedi.com Fri Aug 20 21:36:05 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Fri, 20 Aug 2021 22:36:05 -0300 Subject: on perhaps unloading modules? References: <86pmueu8a5.fsf@jevedi.com> <86k0kghtim.fsf@jevedi.com> Message-ID: <867dgfinp6.fsf@jevedi.com> Greg Ewing writes: > On 21/08/21 6:15 am, Hope Rouselle wrote: >>>>> code() >> 'def p():\n import math\n return math.e\n' >>>>> exec(code()) >>>>> p >> >>>>> p() >> 2.718281828459045 > > Note that this pollutes the globals of the module that you're calling > exec() from. For better isolation you can pass in an explicit globals > dict: > > g = {} > exec(code(), g) > g['p']() Oh! Now I understand how to use it! That's in fact what I was looking for. I noticed it was polluting my environment and was thinking --- hm, that's no good. Thank you. So I believe I understand how to pollute their environment too. Say I have a procedure called external that I'd like to make available to them. It seems this is what I need to do. --8<---------------cut here---------------start------------->8--- def external(): return "external" def run(): s = """ def s(*args): import math return external(), math.e, args """ g = {} exec(s, g) g["external"] = external return g --8<---------------cut here---------------end--------------->8--- >>> student["s"](1, 2) ('external', 2.718281828459045, (1, 2)) That's good. So I can restrict their environment too, by removing some built-ins and so on. (I wish I could restrict their syntax too, though, but I fear that's not possible. For instance, it would be very useful if I could remove loops. If the course doesn't let them use them, it is silly to have to ask them kindly not to use them --- please be patient with this poorly designed course. In reality there is a whole department learning to run a course and there are many students helping this department get a passing grade into how to do it.) :-D Anyhow, your ideas have improved the outlook of this grader quite a lot. Thank you! From hrouselle at jevedi.com Fri Aug 20 21:39:18 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Fri, 20 Aug 2021 22:39:18 -0300 Subject: on slices, negative indices, which are the equivalent procedures? References: <86sfznhk1f.fsf@example.com> <86wnos9ge8.fsf@jevedi.com> <4vi8hg1tfcd2vsrchgpnbpf9a9l7acf7rl@4ax.com> <86a6lj1k7a.fsf@jevedi.com> <86tujkhvhm.fsf@jevedi.com> Message-ID: <86y28vh8zd.fsf@jevedi.com> Hope Rouselle writes: > Dennis Lee Bieber writes: > >> On Sun, 15 Aug 2021 00:05:29 -0300, Jack Brandom >> declaimed the following: >> >>>Dennis Lee Bieber writes: >>> >> >>>> subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] >>>> sliceop: ':' [test] >> >>> >>>This is looking less readable, so, no, I prefer that previous, which was >>>much clearer about slices. I can't even quite make the slices out in >>>these rules. (But thanks for the opportunity to try.) >> >> The last part of "subscript" has the main "slice" notation (stripping >> the quotes) >> >> [test] : [test] >> >> and the "stride" component is [sliceop] being >> >> : [test] > > Let's see. Let ``-->'' mean ``expands to''. Then > > subscript > --> [test] ':' [test] [sliceop] > --> [test] ':' [test] ':' [test] > > Does the brackets mean that its content count be omitted? ^^^^ ^^^^^ _Do_ the brackets mean that its content _can_ be omitted? (This is really too much coffee. It's crazy where my attention goes.) From hrouselle at jevedi.com Fri Aug 20 21:40:13 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Fri, 20 Aug 2021 22:40:13 -0300 Subject: on slices, negative indices, which are the equivalent procedures? References: <86sfznhk1f.fsf@example.com> <86wnos9ge8.fsf@jevedi.com> <4vi8hg1tfcd2vsrchgpnbpf9a9l7acf7rl@4ax.com> <86a6lj1k7a.fsf@jevedi.com> <86tujkhvhm.fsf@jevedi.com> <86y28vh8zd.fsf@jevedi.com> Message-ID: <86sfz3h8xu.fsf@jevedi.com> Hope Rouselle writes: > Hope Rouselle writes: > >> Dennis Lee Bieber writes: >> >>> On Sun, 15 Aug 2021 00:05:29 -0300, Jack Brandom >>> declaimed the following: >>> >>>>Dennis Lee Bieber writes: >>>> >>> >>>>> subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] >>>>> sliceop: ':' [test] >>> >>>> >>>>This is looking less readable, so, no, I prefer that previous, which was >>>>much clearer about slices. I can't even quite make the slices out in >>>>these rules. (But thanks for the opportunity to try.) >>> >>> The last part of "subscript" has the main "slice" notation (stripping >>> the quotes) >>> >>> [test] : [test] >>> >>> and the "stride" component is [sliceop] being >>> >>> : [test] >> >> Let's see. Let ``-->'' mean ``expands to''. Then >> >> subscript >> --> [test] ':' [test] [sliceop] >> --> [test] ':' [test] ':' [test] >> >> Does the brackets mean that its content count be omitted? > ^^^^ ^^^^^ > > _Do_ the brackets mean that its content _can_ be omitted? (This is ^^^ > really too much coffee. It's crazy where my attention goes.) Lol. Should I say _their_ content? I guess so. :-) From george at fischhof.hu Sat Aug 21 08:56:20 2021 From: george at fischhof.hu (George Fischhof) Date: Sat, 21 Aug 2021 14:56:20 +0200 Subject: Making command-line args available to deeply-nested functions In-Reply-To: <878s0wtljf.fsf@hornfels.zedat.fu-berlin.de> References: <87czq8tpay.fsf@hornfels.zedat.fu-berlin.de> <230149ee-f6ed-4e2f-8ac3-c12388ca45acn@googlegroups.com> <878s0wtljf.fsf@hornfels.zedat.fu-berlin.de> Message-ID: Loris Bennett ezt ?rta (id?pont: 2021. aug. 20., P 17:54): > Julio Di Egidio writes: > > > On Friday, 20 August 2021 at 11:54:00 UTC+2, Loris Bennett wrote: > >> Hi, > >> > >> TL;DR: > >> > >> If I have a command-line argument for a program, what is the best way > >> of making this available to a deeply-nested[1] function call without > >> passing the parameter through every intermediate function? > > > > To not pass arguments you need shared state ("global variables"): and > > options in shard state, unless you have very good reasons to do > > otherwise, is simply a no no. > > Doesn't that slightly depend on the size of your "globe"? If a program > does a few, in some sense unrelated things, and, say, only runs for a > few minutes, could you not decide to make a particular parameter global, > even though only one function needs it? In general, however, I would > also avoid this. > > > > >> I can see that the top-level could just create an object from a class > >> which encapsulates everything, but what if I want to keep the salutation > >> generation separate, so that I can have a separate program which just > >> generates the salutation and print it to the terminal? > > > > Yes, that's basically the way to go: parse arguments into a structure (an > > object) that contains all options/parameters then pass that down. Next > level: > > some sections of your code may require a certain subset of those > options, some > > may require some other, so you would structure your options object in > > sub-objects for the various sets of correlated options, then rather pass > just > > the sub-object(s) that are relevant to the section of code you are > calling. > > Variations are of course possible, anyway that's the basic idea. > > > > Also have a look at the "argparse" library, it does all the heavy > lifting for > > the parsing and creation of those objects, definitely advised for in non > trivial > > cases: . > > I am already using 'argparse' ('configargparse' actually). What aspect > should I be looking at in order to produce "sub-objects"? > > >> I guess I am really asking how to avoid "passing through" arguments to > >> functions which only need them to call other functions, so maybe the > >> answer is just to avoid nesting. > > > > No, you don't get rid of code structure just not to pass arguments to > > a function... Code may be poorly structured, but that's another > > story. > > As I am writing new code it is more a question of imposing structure, > rather than getting rid of structure. Unwritten code for a given > purpose obviously has some sort of structure with regards to, say, loops > and conditions, but I am less sure about the implications for how the > code should be nested. Another argument against deeply-nested functions > is the increased complexity of testing. > > Cheers, > > Loris > > -- > This signature is currently under construction. > -- > https://mail.python.org/mailman/listinfo/python-list > > > > Hi, Also you can give a try to click and / or typer packages. Putting args into environment variables can be a solution too All of these depends on several things: personal preferences, colleagues / firm standards, the program, readability, variable accessibility (IDE support, auto completition) (env vars not supported by IDEs as they are not part of code) BR, George From greg.ewing at canterbury.ac.nz Sat Aug 21 06:21:28 2021 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Sat, 21 Aug 2021 22:21:28 +1200 Subject: on perhaps unloading modules? In-Reply-To: <867dgfinp6.fsf@jevedi.com> References: <86pmueu8a5.fsf@jevedi.com> <86k0kghtim.fsf@jevedi.com> <867dgfinp6.fsf@jevedi.com> Message-ID: On 21/08/21 1:36 pm, Hope Rouselle wrote: > I wish I could restrict their syntax too, though, > but I fear that's not possible. For instance, it would be very useful > if I could remove loops. Actually you could, using ast.parse to get an AST and then walk it looking for things you don't want to allow. You could also play around with giving them a custom set of builtins and restricting what they can import. Just be aware that such things are not foolproof, and a sufficiently smart student could find ways around them. (Although if they know that much they probably deserve to pass the course anyway!) -- Greg From hrouselle at jevedi.com Sat Aug 21 10:13:38 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Sat, 21 Aug 2021 11:13:38 -0300 Subject: on perhaps unloading modules? References: <86pmueu8a5.fsf@jevedi.com> <86k0kghtim.fsf@jevedi.com> <867dgfinp6.fsf@jevedi.com> Message-ID: <86a6lahoml.fsf@jevedi.com> Greg Ewing writes: > On 21/08/21 1:36 pm, Hope Rouselle wrote: >> I wish I could restrict their syntax too, though, but I fear that's >> not possible. For instance, it would be very useful if I could >> remove loops. > > Actually you could, using ast.parse to get an AST and then walk > it looking for things you don't want to allow. Very interesting! Thanks very much. That would let me block them, though the ideal would be a certain python.exe binary that simply blows a helpful syntax error when they use something the course doesn't allow. But surely the course could provide students with a certain module or procedure which would validate their work. (Don't turn in unless you pass these verifications.) > You could also play around with giving them a custom set of > builtins and restricting what they can import. Just be aware > that such things are not foolproof, and a sufficiently smart > student could find ways around them. (Although if they know > that much they probably deserve to pass the course anyway!) So true! If they can get around such verifications, they should present their work at an extra-curricular sessions. From josef.kleber at nurfuerspam.de Sat Aug 21 08:21:29 2021 From: josef.kleber at nurfuerspam.de (Josef Kleber) Date: Sat, 21 Aug 2021 14:21:29 +0200 Subject: sting to list of enums Message-ID: Hi, I need to configure a script with a command line switch and/or environment variable (-> string) to a list of enums. I found the following to work: from enum import Enum class Provider(Enum): NONE = 0, '' Amazon = 40, 'Amazon' Netflix = 42, 'Netflix' SkyTicket = 104, 'Sky Ticket' AmazonChannels = 140, 'Amazon Channels' Disney = 176, 'Disney+' def __new__(cls, value, name): member = object.__new__(cls) member._value_ = value member.fullname = name return member def __int__(self): return self.value def __str__(self): return self.fullname providers = [] test = "Amazon, AmazonChannels, Netflix, Disney, SkyTicket" for t in test.split(','): providers.append(Provider[t.strip()]) print(providers) I would prefer a more direct input string like "Provider.Amazon, Provider.Netfilx" Any idea? Or even a better way from cli option to enum list? Josef From talatsteelgleam at gmail.com Sat Aug 21 14:37:05 2021 From: talatsteelgleam at gmail.com (Tony Genter) Date: Sat, 21 Aug 2021 14:37:05 -0400 Subject: tkinter In-Reply-To: <8F7DD012-46A4-4897-85C1-CEF158CC0E4B@hxcore.ol> References: <8F7DD012-46A4-4897-85C1-CEF158CC0E4B@hxcore.ol> Message-ID: <7EF4F665-F41D-4B57-940C-512B7D58D868@hxcore.ol> Tkinter stopped working overnight from 8/20/2021 to 8/21/2021. Last night I was working on tutorials to work on a GUI and this morning every file that uses tkinter is broken stating that no module `tkinter' exists. Please let me know if there is some sort of problem. I am removing visual studios, all versions of python, sublime text, atom, etc and reinstalling all of it to try and resolve the issue. Thanks, Talat Sent from [1]Mail for Windows References Visible links 1. https://go.microsoft.com/fwlink/?LinkId=550986 From rosuav at gmail.com Sat Aug 21 14:43:16 2021 From: rosuav at gmail.com (Chris Angelico) Date: Sun, 22 Aug 2021 04:43:16 +1000 Subject: on perhaps unloading modules? In-Reply-To: <86a6lahoml.fsf@jevedi.com> References: <86pmueu8a5.fsf@jevedi.com> <86k0kghtim.fsf@jevedi.com> <867dgfinp6.fsf@jevedi.com> <86a6lahoml.fsf@jevedi.com> Message-ID: On Sun, Aug 22, 2021 at 4:37 AM Hope Rouselle wrote: > > Greg Ewing writes: > > > On 21/08/21 1:36 pm, Hope Rouselle wrote: > >> I wish I could restrict their syntax too, though, but I fear that's > >> not possible. For instance, it would be very useful if I could > >> remove loops. > > > > Actually you could, using ast.parse to get an AST and then walk > > it looking for things you don't want to allow. > > Very interesting! Thanks very much. That would let me block them, > though the ideal would be a certain python.exe binary that simply blows > a helpful syntax error when they use something the course doesn't allow. > But surely the course could provide students with a certain module or > procedure which would validate their work. (Don't turn in unless you > pass these verifications.) > > > You could also play around with giving them a custom set of > > builtins and restricting what they can import. Just be aware > > that such things are not foolproof, and a sufficiently smart > > student could find ways around them. (Although if they know > > that much they probably deserve to pass the course anyway!) > > So true! If they can get around such verifications, they should present > their work at an extra-curricular sessions. Agreed... if they do it knowingly. On the other hand, if they just turn in code copied blindly from Stack Overflow... ChrisA From martinp.dipaola at gmail.com Sat Aug 21 14:54:11 2021 From: martinp.dipaola at gmail.com (Martin Di Paola) Date: Sat, 21 Aug 2021 18:54:11 +0000 Subject: basic auth request In-Reply-To: References: <54465DA0-2977-4EAD-8CD2-C398F5ACF121@barrys-emacs.org> <9bc605cb-2ceb-fed9-cd3f-d48a8fe405fb@everest.reportlab.co.uk> Message-ID: <20210821185411.ka66xkawv6mbpska@gmail.com> While it is correct to say that Basic Auth without HTTPS is absolutely insecure, using Basic Auth *and* HTTPS is not secure either. Well, the definition of "secure" depends of your threat model. HTTPS ensures encryption so the content, including the Basic Auth username and password, is secret for any external observer. But it is *not* secret for the receiver (the server): if it was compromised an adversary will have access to your password. It is much easier to print a captured password than cracking the hashes. Other authentication mechanisms exist, like OAuth, which are more "secure". Thanks, Martin On Wed, Aug 18, 2021 at 11:05:46PM -0000, Jon Ribbens via Python-list wrote: >On 2021-08-18, Robin Becker wrote: >> On 17/08/2021 22:47, Jon Ribbens via Python-list wrote: >> ....... >>> That's only true if you're not using HTTPS - and you should *never* >>> not be using HTTPS, and that goes double if forms are being filled >>> in and double again if passwords are being supplied. >> >> I think I agree with most of the replies; I understood from reading >> the rfc that the charset is utf8 (presumably without ':') > >The username can't contain a ':'. It shouldn't matter in the password. > >> and that basic auth is considered insecure. It is being used over >> https so should avoid the simplest net scanning. > >It's not insecure over HTTPS. Bear in mind the Basic Auth RFC was >written when HTTP was the standard and HTTPS was unusual. The positions >are now effectively reversed. > >> I googled a bunch of ways to do this, but many come down to 1) using >> the requests package or 2) setting up an opener. Both of these seem to >> be much more complex than is required to add the header. >> >> I thought there might be a shortcut or more elegant way to replace the >> old code, but it seems not > >It's only a trivial str/bytes difference, it shouldn't be any big deal. >But using 'requests' instead is likely to simplify things and doesn't >tend to be an onerous dependency. >-- >https://mail.python.org/mailman/listinfo/python-list From rosuav at gmail.com Sat Aug 21 15:04:43 2021 From: rosuav at gmail.com (Chris Angelico) Date: Sun, 22 Aug 2021 05:04:43 +1000 Subject: basic auth request In-Reply-To: <20210821185411.ka66xkawv6mbpska@gmail.com> References: <54465DA0-2977-4EAD-8CD2-C398F5ACF121@barrys-emacs.org> <9bc605cb-2ceb-fed9-cd3f-d48a8fe405fb@everest.reportlab.co.uk> <20210821185411.ka66xkawv6mbpska@gmail.com> Message-ID: On Sun, Aug 22, 2021 at 4:55 AM Martin Di Paola wrote: > > While it is correct to say that Basic Auth without HTTPS is absolutely > insecure, using Basic Auth *and* HTTPS is not secure either. > > Well, the definition of "secure" depends of your threat model. Yes. Which makes statements like "not secure" rather suspect :) > HTTPS ensures encryption so the content, including the Basic Auth > username and password, is secret for any external observer. > > But it is *not* secret for the receiver (the server): if it was > compromised an adversary will have access to your password. It is much > easier to print a captured password than cracking the hashes. > > Other authentication mechanisms exist, like OAuth, which are more > "secure". If your server is compromised in that way, *all is lost*. If an attacker is actually running code on your server, listening to your sockets, after everything's decrypted, then *shut that server down*. I don't think there is ANY security model that can handle this - if you're using OAuth, and the server is compromised, then your client ID and client secret are just as visible to the attacker as passwords would be. ChrisA From hrouselle at jevedi.com Sat Aug 21 16:15:14 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Sat, 21 Aug 2021 17:15:14 -0300 Subject: on perhaps unloading modules? References: <86pmueu8a5.fsf@jevedi.com> <86k0kghtim.fsf@jevedi.com> <867dgfinp6.fsf@jevedi.com> <86a6lahoml.fsf@jevedi.com> Message-ID: <868s0uftbh.fsf@jevedi.com> Chris Angelico writes: > On Sun, Aug 22, 2021 at 4:37 AM Hope Rouselle wrote: >> >> Greg Ewing writes: >> >> > On 21/08/21 1:36 pm, Hope Rouselle wrote: >> >> I wish I could restrict their syntax too, though, but I fear that's >> >> not possible. For instance, it would be very useful if I could >> >> remove loops. >> > >> > Actually you could, using ast.parse to get an AST and then walk >> > it looking for things you don't want to allow. >> >> Very interesting! Thanks very much. That would let me block them, >> though the ideal would be a certain python.exe binary that simply blows >> a helpful syntax error when they use something the course doesn't allow. >> But surely the course could provide students with a certain module or >> procedure which would validate their work. (Don't turn in unless you >> pass these verifications.) >> >> > You could also play around with giving them a custom set of >> > builtins and restricting what they can import. Just be aware >> > that such things are not foolproof, and a sufficiently smart >> > student could find ways around them. (Although if they know >> > that much they probably deserve to pass the course anyway!) >> >> So true! If they can get around such verifications, they should present >> their work at an extra-curricular sessions. > > Agreed... if they do it knowingly. On the other hand, if they just > turn in code copied blindly from Stack Overflow... When a student does something impressive, we should recognize it. (Don't we do this with ourselves? That's why we should. Not because it's a strategy to sort of encourage the behavior, but because it is our culture.) If if turns out they're clueless about their own feat, we probably would notice by recognizing it in the first time. Being so cool, they could present it to everyone. (This is not a strategy to sort of catch plagiarism, but rather a sober modus operandi that seems to work well.) Copying blindly from somewhere could be the event that triggers a deep interest. One of the things that attracted me to computers was the keyboard. Not sure if it was the first thing. But it's pretty. One time I saw Microsoft Windows and someone let me play on Paint. I loved the B?zier curves and some of the colors. Then came the Internet. Wow! The Internet brought me UNIX and I began to see computer code. I was impressed at how someone could just understand such things. I wanted to write some PHP precisely because it looked so much more cryptic than Allaire ColdFusion. Then C looked even more cryptic, so I fell in love with C. Maybe a little copy from wherever could be the spark for bigger things. Education is a fantastically difficult thing and making mistakes seems so involved with it that it's perhaps undetachable from it. Of course, we should stop ourselves from making irreversible mistakes such as falling from a precipice. From alan.gauld at yahoo.co.uk Sat Aug 21 16:21:18 2021 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Sat, 21 Aug 2021 21:21:18 +0100 Subject: tkinter In-Reply-To: <7EF4F665-F41D-4B57-940C-512B7D58D868@hxcore.ol> References: <8F7DD012-46A4-4897-85C1-CEF158CC0E4B@hxcore.ol> <7EF4F665-F41D-4B57-940C-512B7D58D868@hxcore.ol> Message-ID: On 21/08/2021 19:37, Tony Genter wrote: > Tkinter stopped working overnight from 8/20/2021 to 8/21/2021. Last night > I was working on tutorials to work on a GUI and this morning every file > that uses tkinter is broken stating that no module `tkinter' exists. Are you sure you were running Python v3 and not python v2? In v2 tkinter is spelled Tkinter. If that is the issue then reinstalling python v3.x and ensuring that it is the executable used should resolve the issue. Another option might be that you are using virtual environments which could result in all manner of chaos and confusion if you inadvertently start the wrong one... -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From hjp-python at hjp.at Sat Aug 21 17:25:17 2021 From: hjp-python at hjp.at (Peter J. Holzer) Date: Sat, 21 Aug 2021 23:25:17 +0200 Subject: Python and Ubuntu versions In-Reply-To: References: Message-ID: <20210821212517.GA19129@hjp.at> On 2021-07-23 15:17:59 +1000, Cameron Simpson wrote: > On 23Jul2021 07:54, ???? wrote: > >I have a production server with Ubuntu 18.04 LTS (currently upgraded to > >Ubuntu 18.04.5 LTS) and I use Python in virtualenv - currently Python > >3.6.9. I'm using Django and I read that from Django 4.0, a minimal version > >of Python 3.8 will be required. I would like to know how I use the latest > >version of Python (3.10 or 3.9) with my production server [...] > > I would install a totally separate Python from the vendor (ubunut) > provided one. This prevents subtle changes to what the OS has been > tested against. > > You can built Python from source and install it, for example with a > prefix like /usr/local/ptyhon-3.10. That gets you a different version; > nothing in the OS stuff will try to use it, but you use it to invoke > your Django app. If you are using mod_wsgi to run your Python apps you will probably have to rebuild that as well. The mod_wsgi supplied with Ubuntu uses the system Python and at least a cursory glance through the docs doesn't reveal a way to change that. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From drsalists at gmail.com Sat Aug 21 18:35:21 2021 From: drsalists at gmail.com (Dan Stromberg) Date: Sat, 21 Aug 2021 15:35:21 -0700 Subject: Cyclic imports In-Reply-To: References: <11811693.O9o76ZdvQC@varric.chelsea.private> Message-ID: On Tue, Aug 17, 2021 at 11:20 AM Chris Angelico wrote: > The main advantage of ast.parse() is that it no longer cares about > code layout, and it won't be fooled by an import statement inside a > docstring, or anything like that. It's also pretty easy to handle > multiple variants (note how "import bar, baz" just has two things in > the names list). > I put together something to detect importcycles using the ast module. It's at https://stromberg.dnsalias.org/svn/cycles/trunk for now - no pypi, no homepage. I've only run it on some test inputs, nothing substantial. Usage example is in the Makefile. Imports are kind of complicated. Am I missing any important cases? Sample output looks like: Detected 2 cycles: ('mutual_1', 'mutual_2') ('directory.mutual_a', 'directory.mutual_b', 'directory.mutual_c') Thanks! From drsalists at gmail.com Sat Aug 21 18:48:31 2021 From: drsalists at gmail.com (Dan Stromberg) Date: Sat, 21 Aug 2021 15:48:31 -0700 Subject: Cyclic imports In-Reply-To: References: <11811693.O9o76ZdvQC@varric.chelsea.private> Message-ID: On Sat, Aug 21, 2021 at 3:35 PM Dan Stromberg wrote: > On Tue, Aug 17, 2021 at 11:20 AM Chris Angelico wrote: > >> The main advantage of ast.parse() is that it no longer cares about >> code layout, and it won't be fooled by an import statement inside a >> docstring, or anything like that. It's also pretty easy to handle >> multiple variants (note how "import bar, baz" just has two things in >> the names list). >> > > I put together something to detect importcycles using the ast module. > It's at https://stromberg.dnsalias.org/svn/cycles/trunk for now - no > pypi, no homepage. I've only run it on some test inputs, nothing > substantial. Usage example is in the Makefile. > > Imports are kind of complicated. Am I missing any important cases? > > Sample output looks like: > Detected 2 cycles: > ('mutual_1', 'mutual_2') > ('directory.mutual_a', 'directory.mutual_b', 'directory.mutual_c') > > Thanks! > BTW, "readline0.py" is in the project as a Subversion external reference, so just going to the URL above in a browser won't show it. But you can install an svn binary and then: svn checkout https://stromberg.dnsalias.org/svn/cycles/trunk That should get all of it, including readline0.py From hjp-python at hjp.at Sun Aug 22 04:43:41 2021 From: hjp-python at hjp.at (Peter J. Holzer) Date: Sun, 22 Aug 2021 10:43:41 +0200 Subject: basic auth request In-Reply-To: References: <54465DA0-2977-4EAD-8CD2-C398F5ACF121@barrys-emacs.org> <9bc605cb-2ceb-fed9-cd3f-d48a8fe405fb@everest.reportlab.co.uk> <20210821185411.ka66xkawv6mbpska@gmail.com> Message-ID: <20210822084341.GA13245@hjp.at> On 2021-08-22 05:04:43 +1000, Chris Angelico wrote: > On Sun, Aug 22, 2021 at 4:55 AM Martin Di Paola > wrote: > > > > While it is correct to say that Basic Auth without HTTPS is absolutely > > insecure, using Basic Auth *and* HTTPS is not secure either. > > > > Well, the definition of "secure" depends of your threat model. > > Yes. Which makes statements like "not secure" rather suspect :) Right. > > HTTPS ensures encryption so the content, including the Basic Auth > > username and password, is secret for any external observer. > > > > But it is *not* secret for the receiver (the server): if it was > > compromised an adversary will have access to your password. It is much > > easier to print a captured password than cracking the hashes. > > > > Other authentication mechanisms exist, like OAuth, which are more > > "secure". OAuth is "an /authorization protocol/, rather than an /authentication protocol/" [Wikipedia]. > If your server is compromised in that way, *all is lost*. If "you" are the service provider, yes. but if "you" are the user, no. From a user's perspective "all" is much more than the data (including username and password) associated with that particular service. So if one service is compromised, not all is lost, but only a bit (of course, depending on the importance of the service, that bit may be little or big; a random web forum probably doesn't matter. Your bank account probably does). So assuming that many people reuse passwords (which of course they shouldn't and thanks to password is becoming rarer, but is still distressingly common), there are three levels of security (from highest to lowest) in this scenario: 1: The secret known to the user is never transmitted to the server at all, the client only proves that the secret is known. This is the case for TLS client authentication (which AFAIK all browsers support but is a real pain in the ass to set up, so it's basically never used) and for SCRAM (which isn't part of HTTP(S) but could be implemented in JavaScript). 2: The secret is transmitted on login but never stored. This limits the damage to users who logged in while the server was compromised. This is the case for Basic Authentication combined with a probperly salted hashed storage. 3: The secret is stored on the server. When the server is compromised, all user's passwords are known. This is (AFAIK) the case for Digest and NTLM. So given the choice between Basic Auth and Digest or NTLM (over HTTPS in all cases) I would prefer Basic Auth. Ideally I would use SCRAM or a public key method, but I admit that my security requirements were never high enough to actually bother to do that (actually, I used SSL client side auth once, 20 years ago, ...). hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From rosuav at gmail.com Sun Aug 22 05:37:24 2021 From: rosuav at gmail.com (Chris Angelico) Date: Sun, 22 Aug 2021 19:37:24 +1000 Subject: basic auth request In-Reply-To: <20210822084341.GA13245@hjp.at> References: <54465DA0-2977-4EAD-8CD2-C398F5ACF121@barrys-emacs.org> <9bc605cb-2ceb-fed9-cd3f-d48a8fe405fb@everest.reportlab.co.uk> <20210821185411.ka66xkawv6mbpska@gmail.com> <20210822084341.GA13245@hjp.at> Message-ID: On Sun, Aug 22, 2021 at 6:45 PM Peter J. Holzer wrote: > > On 2021-08-22 05:04:43 +1000, Chris Angelico wrote: > > On Sun, Aug 22, 2021 at 4:55 AM Martin Di Paola > > wrote: > > > HTTPS ensures encryption so the content, including the Basic Auth > > > username and password, is secret for any external observer. > > > > > > But it is *not* secret for the receiver (the server): if it was > > > compromised an adversary will have access to your password. It is much > > > easier to print a captured password than cracking the hashes. > > > > > > Other authentication mechanisms exist, like OAuth, which are more > > > "secure". > > OAuth is "an /authorization protocol/, rather than an /authentication > protocol/" [Wikipedia]. > > > If your server is compromised in that way, *all is lost*. > > If "you" are the service provider, yes. but if "you" are the user, no. If "your server" is compromised, then you are the service provider, are you not? I'm not sure what "your server" would mean if "you" are the user. But okay. Suppose I log in to Random Service 1, using a user name and password, and also to Random Service 2, using OAuth. What happens if those servers get compromised? 1) Someone knows the login credentials that I created for that service. If I've used the same password that I also use at my bank, then I am in big trouble. It is, largely, my fault. 2) Someone has access to my login token and the client ID/secret associated with it. That attacker can now impersonate me to the OAuth provider, to the exact extent that the scopes permit. At absolute least, the attacker gets to know a lot about who I am on some entirely separate service. I'm talking here about a complete and utter compromise, the sort where neither SSL encryption nor proper password hashing would protect my details, since that's what was being claimed. Which is actually worse? Is it as clear-cut? > From a user's perspective "all" is much more than the data (including > username and password) associated with that particular service. So if > one service is compromised, not all is lost, but only a bit (of course, > depending on the importance of the service, that bit may be little or > big; a random web forum probably doesn't matter. Your bank account > probably does). > > So assuming that many people reuse passwords (which of course they > shouldn't and thanks to password is becoming rarer, but is still > distressingly common), True, but reuse of passwords is something under the user's control. OAuth scope selection is partly under the service's control, and partly under the provider's (some providers have extremely coarse scopes, widening the attack). > there are three levels of security (from highest > to lowest) in this scenario: > > 1: The secret known to the user is never transmitted to the server at > all, the client only proves that the secret is known. This is the > case for TLS client authentication (which AFAIK all browsers support > but is a real pain in the ass to set up, so it's basically never > used) and for SCRAM (which isn't part of HTTP(S) but could be > implemented in JavaScript). This would be great, if nobody minded (a) setting up a unique client certificate for every site, or (b) allowing the ultimate in remote tracking cookie whereby any server could recognize you by your TLS certificate. > 2: The secret is transmitted on login but never stored. This limits the > damage to users who logged in while the server was compromised. This > is the case for Basic Authentication combined with a probperly salted > hashed storage. Current best prac, and what I'd generally recommend to most people. > 3: The secret is stored on the server. When the server is compromised, > all user's passwords are known. This is (AFAIK) the case for Digest > and NTLM. I'm not sure what the effects of wide-spread Digest/NTLM usage would have on password managers and the risks of compromise to them, but the way things currently are, I would prefer salted/hashed passwords, such that a data breach doesn't mean compromise of all historical data. > So given the choice between Basic Auth and Digest or NTLM (over HTTPS in > all cases) I would prefer Basic Auth. Ideally I would use SCRAM or a > public key method, but I admit that my security requirements were never > high enough to actually bother to do that (actually, I used SSL client > side auth once, 20 years ago, ...). > I would, of course, prefer something like form fill-out over Basic, but that's due to UI concerns rather than security ones. SCRAM seems tempting, but in a context of web browsers, I'm not sure that it would be worth the hassle. When it comes to security, one thing I'm very curious about is why we don't have any sort of certificate renewal verification. My browser could retain the certificates of some web site (or of all web sites, even - they're not THAT large), and if the site presents a different cert, it could show the previously retained one and challenge the server "prove that you're the same guy". This proof would consist of the latest cert, signed by the older cert's key (or possibly a chain that can construct such a proof, which would allow the server to simply retain each new cert signed by the one previous cert, forming a line - or a tree if necessary). My suspicion is that it'd add little above simply having a valid cert, but if people are paranoid, surely that's a better place to look? ChrisA From barry at barrys-emacs.org Sun Aug 22 06:30:01 2021 From: barry at barrys-emacs.org (Barry Scott) Date: Sun, 22 Aug 2021 11:30:01 +0100 Subject: basic auth request In-Reply-To: References: <54465DA0-2977-4EAD-8CD2-C398F5ACF121@barrys-emacs.org> <9bc605cb-2ceb-fed9-cd3f-d48a8fe405fb@everest.reportlab.co.uk> <20210821185411.ka66xkawv6mbpska@gmail.com> <20210822084341.GA13245@hjp.at> Message-ID: <6ED57509-8AEA-4370-86ED-9F9ED04CA719@barrys-emacs.org> > On 22 Aug 2021, at 10:37, Chris Angelico wrote: > > When it comes to security, one thing I'm very curious about is why we > don't have any sort of certificate renewal verification. My browser > could retain the certificates of some web site (or of all web sites, > even - they're not THAT large), and if the site presents a different > cert, it could show the previously retained one and challenge the > server "prove that you're the same guy". This proof would consist of > the latest cert, signed by the older cert's key (or possibly a chain > that can construct such a proof, which would allow the server to > simply retain each new cert signed by the one previous cert, forming a > line - or a tree if necessary). My suspicion is that it'd add little > above simply having a valid cert, but if people are paranoid, surely > that's a better place to look? The web site proves it owners the hostname and/or IP address using its certificate. You use your trust store to show that you can trust that certificate. The fact that a certificate changes is not a reason to stop trusting a site. So it does not add anything. The pain point in PKI is revocation. The gold standard is for a web site to use OCSP stapling. But that is rare sadly. And because of issues with revocation lists, (privacy, latency, need to fail open on failiure, DoD vector, etc) this is where the paranoid should look. Barry From drsalists at gmail.com Sun Aug 22 10:07:07 2021 From: drsalists at gmail.com (Dan Stromberg) Date: Sun, 22 Aug 2021 07:07:07 -0700 Subject: from foo import bar and the ast module Message-ID: In 'from foo import bar': With the ast module, I see how to get bar, but I do not yet see how to get the foo. There are clearly ast.Import and ast.ImportFrom, but I do not see the foo part in ast.ImportFrom. ? Thanks! From rosuav at gmail.com Sun Aug 22 10:13:12 2021 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 23 Aug 2021 00:13:12 +1000 Subject: from foo import bar and the ast module In-Reply-To: References: Message-ID: On Mon, Aug 23, 2021 at 12:08 AM Dan Stromberg wrote: > > In 'from foo import bar': > > With the ast module, I see how to get bar, but I do not yet see how to get > the foo. > > There are clearly ast.Import and ast.ImportFrom, but I do not see the foo > part in ast.ImportFrom. > > ? >>> import ast >>> ast.dump(ast.parse("from foo import bar")) "Module(body=[ImportFrom(module='foo', names=[alias(name='bar')], level=0)], type_ignores=[])" >>> ast.parse("from foo import bar").body[0].module 'foo' ChrisA From drsalists at gmail.com Sun Aug 22 10:26:12 2021 From: drsalists at gmail.com (Dan Stromberg) Date: Sun, 22 Aug 2021 07:26:12 -0700 Subject: from foo import bar and the ast module In-Reply-To: References: Message-ID: On Sun, Aug 22, 2021 at 7:14 AM Chris Angelico wrote: > On Mon, Aug 23, 2021 at 12:08 AM Dan Stromberg > wrote: > > > > In 'from foo import bar': > > > > With the ast module, I see how to get bar, but I do not yet see how to > get > > the foo. > > > > There are clearly ast.Import and ast.ImportFrom, but I do not see the foo > > part in ast.ImportFrom. > > > > ? > > >>> import ast > >>> ast.dump(ast.parse("from foo import bar")) > "Module(body=[ImportFrom(module='foo', names=[alias(name='bar')], > level=0)], type_ignores=[])" > >>> ast.parse("from foo import bar").body[0].module > 'foo' > With 'from . import bar', I get a module of None. Does this seem strange? From rosuav at gmail.com Sun Aug 22 10:35:25 2021 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 23 Aug 2021 00:35:25 +1000 Subject: from foo import bar and the ast module In-Reply-To: References: Message-ID: On Mon, Aug 23, 2021 at 12:26 AM Dan Stromberg wrote: > > > On Sun, Aug 22, 2021 at 7:14 AM Chris Angelico wrote: >> >> On Mon, Aug 23, 2021 at 12:08 AM Dan Stromberg wrote: >> > >> > In 'from foo import bar': >> > >> > With the ast module, I see how to get bar, but I do not yet see how to get >> > the foo. >> > >> > There are clearly ast.Import and ast.ImportFrom, but I do not see the foo >> > part in ast.ImportFrom. >> > >> > ? >> >> >>> import ast >> >>> ast.dump(ast.parse("from foo import bar")) >> "Module(body=[ImportFrom(module='foo', names=[alias(name='bar')], >> level=0)], type_ignores=[])" >> >>> ast.parse("from foo import bar").body[0].module >> 'foo' > > > With 'from . import bar', I get a module of None. > > Does this seem strange? > No; it's just the AST so it can't bring in any additional information. To distinguish package-relative imports, use the level attribute: >>> ast.dump(ast.parse("from . import bar").body[0]) "ImportFrom(names=[alias(name='bar')], level=1)" >>> ast.dump(ast.parse("from .foo import bar").body[0]) "ImportFrom(module='foo', names=[alias(name='bar')], level=1)" >>> ast.dump(ast.parse("from foo.bar import bar").body[0]) "ImportFrom(module='foo.bar', names=[alias(name='bar')], level=0)" >>> ast.dump(ast.parse("from .foo.bar import bar").body[0]) "ImportFrom(module='foo.bar', names=[alias(name='bar')], level=1)" >>> ast.dump(ast.parse("from ..foo.bar import bar").body[0]) "ImportFrom(module='foo.bar', names=[alias(name='bar')], level=2)" ChrisA From hrouselle at jevedi.com Sun Aug 22 05:30:38 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Sun, 22 Aug 2021 06:30:38 -0300 Subject: on perhaps unloading modules? References: <86pmueu8a5.fsf@jevedi.com> <861r6pgx12.fsf@jevedi.com> Message-ID: <86wnodrflt.fsf@jevedi.com> Hope Rouselle writes: > Chris Angelico writes: > >> On Tue, Aug 17, 2021 at 4:02 AM Greg Ewing >> wrote: >>> The second best way would be to not use import_module, but to >>> exec() the student's code. That way you don't create an entry in >>> sys.modules and don't have to worry about somehow unloading the >>> module. >> >> I would agree with this. If you need to mess around with modules and >> you don't want them to be cached, avoid the normal "import" mechanism, >> and just exec yourself a module's worth of code. > > Sounds like a plan. Busy, haven't been able to try it out. But I will. > Soon. Thank you! Just to close off this thread, let me share a bit of what I wrote. The result is a lot better. Thanks for all the help! I exec the student's code into a dictionary g. --8<---------------cut here---------------start------------->8--- def fs_read(fname): with open(fname, "r") as f: return f.read() def get_student_module_exec(fname): g = {} try: student_code = fs_read(fname) student = exec(student_code, g) except Exception as e: return False, str(e) return True, g def get_student_module(fname): return get_student_module_exec(fname) --8<---------------cut here---------------end--------------->8--- And now write the test's key as if I were a student and named my test as "test_key.py". --8<---------------cut here---------------start------------->8--- def get_key(): okay, k = get_student_module("test_key.py") if not okay: # Stop everything. ... return g --8<---------------cut here---------------end--------------->8--- The procedure for grading a question consumes the student's code as a dictionary /s/, grabs the key as /k/ and checks whether the procedures are the same. So, suppose I want to check whether a certain function /fn/ written in the student's dictionary-code /s/ matches the key's. Then I invoke check_student_procedure(k, s, fn). --8<---------------cut here---------------start------------->8--- def check_student_procedure(k, s, fn, args = [], wrap = identity): return check_functions_equal(g[fn], s.get(fn, None), args, wrap) --8<---------------cut here---------------end--------------->8--- For completeness, here's check_functions_equal. --8<---------------cut here---------------start------------->8--- def check_functions_equal(fn_original, fn_candidate, args = [], wrap = identity): flag, e = is_function_executable(fn_candidate, args) if not flag: return False, "runtime", e # run original and student's code, then compare them answer_correct = fn_original(*args) answer_student = wrap(fn_candidate(*args)) if answer_correct != answer_student: return False, None, str(answer_student) return True, None, None def identity(x): return x --8<---------------cut here---------------end--------------->8--- To explain my extra complication there: sometimes I'm permissive with student's answers. Suppose a question requires a float as an answer but in some cases the answer is a whole number --- such as 1.0. If the student ends up producing an int, the student gets that case right: I wrap the student's answer in a float() and the check turns out successful. I probably don't need to check whether a procedure is executable first, but I decided to break the procedure into two such steps. --8<---------------cut here---------------start------------->8--- def is_function_executable(f, args = []): try: f(*args) except Exception as e: return False, str(e) return True, None --8<---------------cut here---------------end--------------->8--- From rosuav at gmail.com Sun Aug 22 07:03:09 2021 From: rosuav at gmail.com (Chris Angelico) Date: Sun, 22 Aug 2021 21:03:09 +1000 Subject: basic auth request In-Reply-To: <6ED57509-8AEA-4370-86ED-9F9ED04CA719@barrys-emacs.org> References: <54465DA0-2977-4EAD-8CD2-C398F5ACF121@barrys-emacs.org> <9bc605cb-2ceb-fed9-cd3f-d48a8fe405fb@everest.reportlab.co.uk> <20210821185411.ka66xkawv6mbpska@gmail.com> <20210822084341.GA13245@hjp.at> <6ED57509-8AEA-4370-86ED-9F9ED04CA719@barrys-emacs.org> Message-ID: On Sun, Aug 22, 2021 at 8:30 PM Barry Scott wrote: > > > > On 22 Aug 2021, at 10:37, Chris Angelico wrote: > > When it comes to security, one thing I'm very curious about is why we > don't have any sort of certificate renewal verification. My browser > could retain the certificates of some web site (or of all web sites, > even - they're not THAT large), and if the site presents a different > cert, it could show the previously retained one and challenge the > server "prove that you're the same guy". This proof would consist of > the latest cert, signed by the older cert's key (or possibly a chain > that can construct such a proof, which would allow the server to > simply retain each new cert signed by the one previous cert, forming a > line - or a tree if necessary). My suspicion is that it'd add little > above simply having a valid cert, but if people are paranoid, surely > that's a better place to look? > > > The web site proves it owners the hostname and/or IP address using its certificate. > You use your trust store to show that you can trust that certificate. > > The fact that a certificate changes is not a reason to stop trusting a site. > > So it does not add anything. > > The pain point in PKI is revocation. The gold standard is for a web site to use OCSP stapling. > But that is rare sadly. And because of issues with revocation lists, (privacy, latency, need to > fail open on failiure, DoD vector, etc) this is where the paranoid should look. > Fair point. Let me give you a bit of context. Recently, the owner/operator of a site (I'll call it https://demo.example/ ) died. Other people, who have been using the site extensively, wish for it to continue. If the domain registration expires, anyone can reregister it, and can then generate a completely new certificate for the common name "demo.example", and web browsers will accept that. The old cert may or may not have expired, but it won't be revoked. As far as I can tell, a web browser with default settings will happily accept the change of ownership. It won't care that the IP address, certificate, etc, have all changed. It just acknowledges that some CA has signed some certificate with the right common name. And therein is the vulnerability. (NOTE: I'm not saying that this is a real and practical vulnerability - this is theoretical only, and a focus for the paranoid.) This is true even if the old cert were one of those enhanced certificates that some CAs try to upsell you to ("Extended Validation" and friends). Even if, in the past, your bank was secured by one of those certs, your browser will still accept a perfectly standard cert next time. Which, in my opinion, renders those (quite pricey) certificates no more secure than something from Let's Encrypt that has no validation beyond ownership of DNS. Of course, you can pin a certificate. You can ask your browser to warn you if it's changed *at all*. But since certs expire, that's highly impractical, hence wondering why we don't have a system for using the old cert to prove ownership of the new one. So how is a web browser supposed to distinguish between (a) normal operation in which certs expire and are replaced, and (b) legit or non-legit ownership changes? (Of course the browser can't tell you whether the ownership change is legit, but out-of-band info can help with that.) Or does it really matter that little? ChrisA From wlfraed at ix.netcom.com Sun Aug 22 12:18:07 2021 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Sun, 22 Aug 2021 12:18:07 -0400 Subject: on perhaps unloading modules? References: <86k0kghtim.fsf@jevedi.com> <867dgfinp6.fsf@jevedi.com> <86a6lahoml.fsf@jevedi.com> <868s0uftbh.fsf@jevedi.com> Message-ID: <7st4ig986242i36gqemgr5e1kub6s8t6ld@4ax.com> On Sat, 21 Aug 2021 17:15:14 -0300, Hope Rouselle declaimed the following: >write some PHP precisely because it looked so much more cryptic than >Allaire ColdFusion. Then C looked even more cryptic, so I fell in love >with C. > Try APL then... (I suspect this will get garbaged in processing...) 4 5 ? 20 ? 52 (it did... the first ? [in my display] is Greek lower case rho, the second question mark is... a question mark). 4 5 $RHO 20 ? 52 Generate 20 random numbers in the range 1..52, no duplicates, reshape the vector into a 4x5 matrix. That just "dealt" four poker hands (needs logic to translate integer 1..52 into suit/rank). -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From mohsen.owzar at gmail.com Sun Aug 22 09:04:42 2021 From: mohsen.owzar at gmail.com (Mohsen Owzar) Date: Sun, 22 Aug 2021 06:04:42 -0700 (PDT) Subject: PyQt5 is not recognized from python 3.8 installation in python 3.10 Message-ID: Hi guys, I have on my laptop the python installation 3.8 and newly I installed newest version 3.10 as well on my laptop. Now I have two IDLEs for both of the installations. When I rund some *.py file, having PyQt5 module, on the 3.8 version, it works as before without any problems. But whenn I run the same file on IDLE with 3.10 installation, it crashes and says that PyQt5 is not known. I tried to install this package with"pip install pyqt5" or with "py -3 -m pip install pyqt5", it brings lots of error messages (long long) as the lines below (they are only the beginning of the messages): ================================================== C:\Users\Mohsen>py -3 -m pip install pyqt5 Collecting pyqt5 Using cached PyQt5-5.15.4.tar.gz (3.3 MB) Installing build dependencies ... done Getting requirements to build wheel ... done Preparing wheel metadata ... error ERROR: Command errored out with exit status 1: command: 'C:\Users\Mohsen\AppData\Local\Programs\Python\Python310\python.exe' 'C:\Users\Mohsen\AppData\Local\Programs\Python\Python310\lib\site-packages\pip\_vendor\pep517\in_process\_in_process.py' prepare_metadata_for_build_wheel 'C:\Users\Mohsen\AppData\Local\Temp\tmprax0esmt' cwd: C:\Users\Mohsen\AppData\Local\Temp\pip-install-wl_b58e9\pyqt5_1cbd1bab46fa4abaad34b55514561ce6 Complete output (33 lines): Querying qmake about your Qt installation... C:\Qt\4.7.4\bin\qmake.exe -query Traceback (most recent call last): File "C:\Users\Mohsen\AppData\Local\Programs\Python\Python310\lib\site-packages\pip\_vendor\pep517\in_process\_in_process.py", line 143, in prepare_metadata_for_build_wheel hook = backend.prepare_metadata_for_build_wheel AttributeError: module 'sipbuild.api' has no attribute 'prepare_metadata_for_build_wheel' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "C:\Users\Mohsen\AppData\Local\Programs\Python\Python310\lib\site-packages\pip\_vendor\pep517\in_process\_in_process.py", line 349, in main() File "C:\Users\Mohsen\AppData\Local\Programs\Python\Python310\lib\site-packages\pip\_vendor\pep517\in_process\_in_process.py", line 331, in main json_out['return_val'] = hook(**hook_input['kwargs']) ============================================== It begins with "PyQt5-5.15.4.tar.gz" and goes down "PyQt5-5.15.3.tar.gz" and so on, after it cannot install that version. After it reaches the "PyQt5-5.14.0.tar.gz" it breaks the downloading and bring this message ============================================== WARNING: Discarding https://files.pythonhosted.org/packages/3a/fb/eb51731f2dc7c22d8e1a63ba88fb702727b324c6352183a32f27f73b8116/PyQt5-5.14.1.tar.gz#sha256=2f230f2dbd767099de7a0cb915abdf0cbc3256a0b5bb910eb09b99117db7a65b (from https://pypi.org/simple/pyqt5/) (requires-python:>=3.5). Command errored out with exit status 1: 'C:\Users\Mohsen\AppData\Local\Programs\Python\Python310\python.exe' 'C:\Users\Mohsen\AppData\Local\Programs\Python\Python310\lib\site-packages\pip\_vendor\pep517\in_process\_in_process.py' prepare_metadata_for_build_wheel 'C:\Users\Mohsen\AppData\Local\Temp\tmp6t_i9jm7' Check the logs for full command output. Downloading PyQt5-5.14.0.tar.gz (3.2 MB) |????????????????????????????????| 3.2 MB 3.3 MB/s ERROR: pyqt5 from https://files.pythonhosted.org/packages/7c/5b/e760ec4f868cb77cee45b4554bf15d3fe6972176e89c4e3faac941213694/PyQt5-5.14.0.tar.gz#sha256=0145a6b7de15756366decb736c349a0cb510d706c83fda5b8cd9e0557bc1da72 has a pyproject.toml file that does not comply with PEP 518: 'build-system.requires' contains an invalid requirement: 'sip >=5.0.1 <6' ============================================== What is wrong with my installations. How can I get all the packages available in 3.8 version also available for 3.10 version without any new installation in 3.10 for each all already existing packages? Thanks a lot in advance for you contributions. Mohsen From python at mrabarnett.plus.com Sun Aug 22 14:57:35 2021 From: python at mrabarnett.plus.com (MRAB) Date: Sun, 22 Aug 2021 19:57:35 +0100 Subject: on perhaps unloading modules? In-Reply-To: <7st4ig986242i36gqemgr5e1kub6s8t6ld@4ax.com> References: <86k0kghtim.fsf@jevedi.com> <867dgfinp6.fsf@jevedi.com> <86a6lahoml.fsf@jevedi.com> <868s0uftbh.fsf@jevedi.com> <7st4ig986242i36gqemgr5e1kub6s8t6ld@4ax.com> Message-ID: <2e77100d-b919-9afc-5c4a-d99124d953e0@mrabarnett.plus.com> On 2021-08-22 17:18, Dennis Lee Bieber wrote: > On Sat, 21 Aug 2021 17:15:14 -0300, Hope Rouselle > declaimed the following: > >>write some PHP precisely because it looked so much more cryptic than >>Allaire ColdFusion. Then C looked even more cryptic, so I fell in love >>with C. >> > Try APL then... > > (I suspect this will get garbaged in processing...) > > 4 5 ? 20 ? 52 > 4 5 ? 20 ? 52 > (it did... the first ? [in my display] is Greek lower case rho, the second > question mark is... a question mark). > The headers say that the encoding is ASCII. > 4 5 $RHO 20 ? 52 > > Generate 20 random numbers in the range 1..52, no duplicates, reshape > the vector into a 4x5 matrix. > > That just "dealt" four poker hands (needs logic to translate integer > 1..52 into suit/rank). > From rosuav at gmail.com Sun Aug 22 15:28:00 2021 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 23 Aug 2021 05:28:00 +1000 Subject: PyQt5 is not recognized from python 3.8 installation in python 3.10 In-Reply-To: References: Message-ID: On Mon, Aug 23, 2021 at 4:31 AM Mohsen Owzar wrote: > How can I get all the packages available in 3.8 version also available for 3.10 version without any new installation in 3.10 for each all already existing packages? > You can't. With compiled binaries, especially, it's important to install into each version separately - there can be minor differences which will be taken care of by the installer. Normally, that's not a problem, other than that you have to install each one again; the best way would be to keep track of your package dependencies in a file called requirements.txt, and then you can simply install from that (python3 -m pip install -r requirements.txt) into the new version. As to PyQt5 specifically, though.... I don't know what the issue here is, but I tried it on my system and it successfully installed version 5.15.4. Are you using the latest version of pip? There might be some other requirements. Alternatively, I'm seeing a potential red flag from this line: > C:\Qt\4.7.4\bin\qmake.exe -query You're trying to install Qt5, but maybe it's coming across a Qt4 installation? Not sure if that's significant or not. ChrisA From mats at wichmann.us Sun Aug 22 18:55:28 2021 From: mats at wichmann.us (Mats Wichmann) Date: Sun, 22 Aug 2021 16:55:28 -0600 Subject: PyQt5 is not recognized from python 3.8 installation in python 3.10 In-Reply-To: References: Message-ID: On 8/22/21 7:04 AM, Mohsen Owzar wrote: > Hi guys, > I have on my laptop the python installation 3.8 and newly I installed newest version 3.10 as well on my laptop. > Now I have two IDLEs for both of the installations. > When I rund some *.py file, having PyQt5 module, on the 3.8 version, it works as before without any problems. > But whenn I run the same file on IDLE with 3.10 installation, it crashes and says that PyQt5 is not known. > > I tried to install this package with"pip install pyqt5" or with "py -3 -m pip install pyqt5", it brings lots of error messages (long long) as the lines below (they are only the beginning of the messages): make sure you're getting the right Python by doing py -3.10 -m pip install pyqt5 (the fact you're getting the build error below indicates you _are_ getting the right one, but it's good to be explicit anyway, just so you're sure). > ================================================== > C:\Users\Mohsen>py -3 -m pip install pyqt5 > Collecting pyqt5 > Using cached PyQt5-5.15.4.tar.gz (3.3 MB) > Installing build dependencies ... done > Getting requirements to build wheel ... done > Preparing wheel metadata ... error > ERROR: Command errored out with exit status 1: > command: 'C:\Users\Mohsen\AppData\Local\Programs\Python\Python310\python.exe' 'C:\Users\Mohsen\AppData\Local\Programs\Python\Python310\lib\site-packages\pip\_vendor\pep517\in_process\_in_process.py' prepare_metadata_for_build_wheel 'C:\Users\Mohsen\AppData\Local\Temp\tmprax0esmt' > cwd: C:\Users\Mohsen\AppData\Local\Temp\pip-install-wl_b58e9\pyqt5_1cbd1bab46fa4abaad34b55514561ce6 > Complete output (33 lines): > Querying qmake about your Qt installation... > C:\Qt\4.7.4\bin\qmake.exe -query > Traceback (most recent call last): > File "C:\Users\Mohsen\AppData\Local\Programs\Python\Python310\lib\site-packages\pip\_vendor\pep517\in_process\_in_process.py", line 143, in prepare_metadata_for_build_wheel > hook = backend.prepare_metadata_for_build_wheel > AttributeError: module 'sipbuild.api' has no attribute 'prepare_metadata_for_build_wheel' Your problem here is that there's no released binary wheel for PyQt5, since Py 3.10 isn't released (there's been some recent chatter about encouraging projects to make builds for new Python versions available early, e.g. once a Python version hits release candidate state, but that's just that - chatter - for now). In theory your system should be able to build it, but my experience is that unless you're an active Python developer on Windows and already have the right working setup, it pretty much always fails. These are the perils of trying to use a pre-release... That error suggests there's something different going on than usual (which has to do with the MSVC compiler suite not being set up the way the package expects): there looks like a version mismatch - it looks like it's finding qmake for Qt4, not Qt5. Maybe you can make some progress by adjusting some paths? Many people go here to get early-access, albeit unofficial, binary wheels: https://www.lfd.uci.edu/~gohlke/pythonlibs Unfortunately, PyQt5 is not available from there (as listed in the section at the very bottom) From hrouselle at jevedi.com Sun Aug 22 15:28:12 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Sun, 22 Aug 2021 16:28:12 -0300 Subject: on perhaps unloading modules? References: <86k0kghtim.fsf@jevedi.com> <867dgfinp6.fsf@jevedi.com> <86a6lahoml.fsf@jevedi.com> <868s0uftbh.fsf@jevedi.com> <7st4ig986242i36gqemgr5e1kub6s8t6ld@4ax.com> Message-ID: <86o89p9t4j.fsf@jevedi.com> Dennis Lee Bieber writes: > On Sat, 21 Aug 2021 17:15:14 -0300, Hope Rouselle > declaimed the following: > >>write some PHP precisely because it looked so much more cryptic than >>Allaire ColdFusion. Then C looked even more cryptic, so I fell in love >>with C. >> > Try APL then... Lol. If the code below is APL, then thanks, but no, thanks. :-) We change over the years. These days I'm more or less obsessed with clarity. For instance, I'm a lot into literate programming Knuth-style. I have a certain distaste for syntax too. For instance, I would much rather write and read ``first(ls)'' than ``ls[0]''. I can't see too much advantage in using more syntax for something that procedures could do. But, of course, in certain contexts it might be better to write ls[0] or something like that. In these cases, the writer could then make the case and then define the new syntax, so I do think that writers should have the power to change syntax. I'm well aware of the double-edged sword this is. (Incidentally, yesterday I was happily reading a Python programmer talking about [1] how Dijkstra got it right for suggesting we shouldn't be using goto. Knuth had the opinion that it'd be a shame to remove goto, even though, of course, he'd agree that people should learn how to use it.) Is syntax the same thing as goto? I'm not sure. If it is, then I am like Knuth --- I feel sad when languages remove my ability to change syntax. But surely I feel overwhelmed sometimes when there's too much syntax created by the programmer who wrote the library that I'm trying to understand. (*) Footnotes [1] Notes on structured concurrency https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful > (I suspect this will get garbaged in processing...) > > 4 5 ? 20 ? 52 > > (it did... the first ? [in my display] is Greek lower case rho, the second > question mark is... a question mark). Like you, I see two question marks. > 4 5 $RHO 20 ? 52 > > Generate 20 random numbers in the range 1..52, no duplicates, reshape > the vector into a 4x5 matrix. > > That just "dealt" four poker hands (needs logic to translate integer > 1..52 into suit/rank). That's wild. :-) Was this created by Brian Kernighan? It's hard to believe. Oh, I think he wrote AMPL, wasn't it? A Mathematical Programming Language, or something like that. From loris.bennett at fu-berlin.de Mon Aug 23 05:12:09 2021 From: loris.bennett at fu-berlin.de (Loris Bennett) Date: Mon, 23 Aug 2021 11:12:09 +0200 Subject: Decoding of EmailMessage text Message-ID: <87wnocy17a.fsf@hornfels.zedat.fu-berlin.de> Hi, I have written a command-line program to send email using from email.message import EmailMessage which has an option '--verbose' which prints the email via if args.verbose: print(f"{mail.as_string()}") If I run this with $ poetry run send_email loris -l en -s "Another test" -t ~/tmp/blorp_bleep.txt --verbose the following is printed to the terminal: Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 MIME-Version: 1.0 From: hpc at zedat.fu-berlin.de To: loris at zedat.fu-berlin.de Subject: Another test RGVhciBEci4gQmVubmV0dCwKCkJsb3JwISBCbGVlcCEKCgotLQpNYWlsYm90IEluYy4KMDEwMTAx ? IEJvdCBCb3VsZXZhcmQKQm90aGFtIENpdHkKQsO2dGxhbmQK However I would like to see the text as Dear Dr. Bennett, Blorp! Bleep! Regards, Mailbot -- Mailbot Inc. 010101 Bot Boulevard Botham City B?tland which is how the text appears in the mail. The '?' in 'B?tland' triggers the encoding - with 'Botland' the text printed to the terminal is the same way as that in the mail. How do I decode the message properly for an terminal which uss UTF-8? Regards Loris -- This signature is currently under construction. From loris.bennett at fu-berlin.de Mon Aug 23 05:27:58 2021 From: loris.bennett at fu-berlin.de (Loris Bennett) Date: Mon, 23 Aug 2021 11:27:58 +0200 Subject: Making command-line args available to deeply-nested functions References: <87czq8tpay.fsf@hornfels.zedat.fu-berlin.de> <230149ee-f6ed-4e2f-8ac3-c12388ca45acn@googlegroups.com> <878s0wtljf.fsf@hornfels.zedat.fu-berlin.de> Message-ID: <87sfz0y0gx.fsf@hornfels.zedat.fu-berlin.de> George Fischhof writes: > Loris Bennett ezt ?rta (id?pont: 2021. aug. > 20., P 17:54): > >> Julio Di Egidio writes: >> >> > On Friday, 20 August 2021 at 11:54:00 UTC+2, Loris Bennett wrote: >> >> Hi, >> >> >> >> TL;DR: >> >> >> >> If I have a command-line argument for a program, what is the best way >> >> of making this available to a deeply-nested[1] function call without >> >> passing the parameter through every intermediate function? >> > >> > To not pass arguments you need shared state ("global variables"): and >> > options in shard state, unless you have very good reasons to do >> > otherwise, is simply a no no. >> >> Doesn't that slightly depend on the size of your "globe"? If a program >> does a few, in some sense unrelated things, and, say, only runs for a >> few minutes, could you not decide to make a particular parameter global, >> even though only one function needs it? In general, however, I would >> also avoid this. >> >> > >> >> I can see that the top-level could just create an object from a class >> >> which encapsulates everything, but what if I want to keep the salutation >> >> generation separate, so that I can have a separate program which just >> >> generates the salutation and print it to the terminal? >> > >> > Yes, that's basically the way to go: parse arguments into a structure (an >> > object) that contains all options/parameters then pass that down. Next >> level: >> > some sections of your code may require a certain subset of those >> options, some >> > may require some other, so you would structure your options object in >> > sub-objects for the various sets of correlated options, then rather pass >> just >> > the sub-object(s) that are relevant to the section of code you are >> calling. >> > Variations are of course possible, anyway that's the basic idea. >> > >> > Also have a look at the "argparse" library, it does all the heavy >> lifting for >> > the parsing and creation of those objects, definitely advised for in non >> trivial >> > cases: . >> >> I am already using 'argparse' ('configargparse' actually). What aspect >> should I be looking at in order to produce "sub-objects"? >> >> >> I guess I am really asking how to avoid "passing through" arguments to >> >> functions which only need them to call other functions, so maybe the >> >> answer is just to avoid nesting. >> > >> > No, you don't get rid of code structure just not to pass arguments to >> > a function... Code may be poorly structured, but that's another >> > story. >> >> As I am writing new code it is more a question of imposing structure, >> rather than getting rid of structure. Unwritten code for a given >> purpose obviously has some sort of structure with regards to, say, loops >> and conditions, but I am less sure about the implications for how the >> code should be nested. Another argument against deeply-nested functions >> is the increased complexity of testing. [snip (15 lines)]> > Hi, > > Also you can give a try to click and / or typer packages. > Putting args into environment variables can be a solution too > All of these depends on several things: personal preferences, colleagues / > firm standards, the program, readability, variable accessibility (IDE > support, auto completition) (env vars not supported by IDEs as they are not > part of code) Thanks for the pointers, although I have only just got my head around argparse/configargparse, so click is something I might have a look at for future project. However, the question of how to parse the arguments is somewhat separate from that of how to pass (or not pass) the arguments around within a program. Cheers, Loris -- This signature is currently under construction. From loris.bennett at fu-berlin.de Mon Aug 23 06:00:00 2021 From: loris.bennett at fu-berlin.de (Loris Bennett) Date: Mon, 23 Aug 2021 12:00:00 +0200 Subject: Decoding of EmailMessage text References: <87wnocy17a.fsf@hornfels.zedat.fu-berlin.de> Message-ID: <87o89oxyzj.fsf@hornfels.zedat.fu-berlin.de> "Loris Bennett" writes: > Hi, > > I have written a command-line program to send email using > > from email.message import EmailMessage > > which has an option '--verbose' which prints the email via > > if args.verbose: > print(f"{mail.as_string()}") > > If I run this with > > $ poetry run send_email loris -l en -s "Another test" -t ~/tmp/blorp_bleep.txt --verbose > > the following is printed to the terminal: > > Content-Type: text/plain; charset="utf-8" > Content-Transfer-Encoding: base64 > MIME-Version: 1.0 > From: hpc at zedat.fu-berlin.de > To: loris at zedat.fu-berlin.de > Subject: Another test > > RGVhciBEci4gQmVubmV0dCwKCkJsb3JwISBCbGVlcCEKCgotLQpNYWlsYm90IEluYy4KMDEwMTAx ? > IEJvdCBCb3VsZXZhcmQKQm90aGFtIENpdHkKQsO2dGxhbmQK > > However I would like to see the text as > > Dear Dr. Bennett, > > Blorp! Bleep! > > Regards, > > Mailbot > > -- > Mailbot Inc. > 010101 Bot Boulevard > Botham City > B?tland > > which is how the text appears in the mail. > > The '?' in 'B?tland' triggers the encoding - with 'Botland' the text > printed to the terminal is the same way as that in the mail. > > How do I decode the message properly for an terminal which uss UTF-8? If I do From: "Loris Bennett" Newsgroups: comp.lang.python Subject: Re: Decoding of EmailMessage text Gcc: "nnimap+fu_exchange:Gesendete Elemente" --text follows this line-- "Loris Bennett" writes: > Hi, > > I have written a command-line program to send email using > > from email.message import EmailMessage > > which has an option '--verbose' which prints the email via > > if args.verbose: > print(f"{mail.as_string()}") > > If I run this with > > $ poetry run send_email loris -l en -s "Another test" -t ~/tmp/blorp_bleep.txt --verbose > > the following is printed to the terminal: > > Content-Type: text/plain; charset="utf-8" > Content-Transfer-Encoding: base64 > MIME-Version: 1.0 > From: hpc at zedat.fu-berlin.de > To: loris at zedat.fu-berlin.de > Subject: Another test > > RGVhciBEci4gQmVubmV0dCwKCkJsb3JwISBCbGVlcCEKCgotLQpNYWlsYm90IEluYy4KMDEwMTAx ? > IEJvdCBCb3VsZXZhcmQKQm90aGFtIENpdHkKQsO2dGxhbmQK > > However I would like to see the text as > > Dear Dr. Bennett, > > Blorp! Bleep! > > Regards, > > Mailbot > > -- > Mailbot Inc. > 010101 Bot Boulevard > Botham City > B?tland > > which is how the text appears in the mail. > > The '?' in 'B?tland' triggers the encoding - with 'Botland' the text > printed to the terminal is the same way as that in the mail. > > How do I decode the message properly for an terminal which uss UTF-8? If I do From: "Loris Bennett" Newsgroups: comp.lang.python Subject: Re: Decoding of EmailMessage text Gcc: "nnimap+fu_exchange:Gesendete Elemente" --text follows this line-- "Loris Bennett" writes: > Hi, > > I have written a command-line program to send email using > > from email.message import EmailMessage > > which has an option '--verbose' which prints the email via > > if args.verbose: > print(f"{mail.as_string()}") > > If I run this with > > $ poetry run send_email loris -l en -s "Another test" -t ~/tmp/blorp_bleep.txt --verbose > > the following is printed to the terminal: > > Content-Type: text/plain; charset="utf-8" > Content-Transfer-Encoding: base64 > MIME-Version: 1.0 > From: hpc at zedat.fu-berlin.de > To: loris at zedat.fu-berlin.de > Subject: Another test > > RGVhciBEci4gQmVubmV0dCwKCkJsb3JwISBCbGVlcCEKCgotLQpNYWlsYm90IEluYy4KMDEwMTAx ? > IEJvdCBCb3VsZXZhcmQKQm90aGFtIENpdHkKQsO2dGxhbmQK > > However I would like to see the text as > > Dear Dr. Bennett, > > Blorp! Bleep! > > Regards, > > Mailbot > > -- > Mailbot Inc. > 010101 Bot Boulevard > Botham City > B?tland > > which is how the text appears in the mail. > > The '?' in 'B?tland' triggers the encoding - with 'Botland' the text > printed to the terminal is the same way as that in the mail. > > How do I decode the message properly for an terminal which uss UTF-8? If instead of mail.set_content(body) I do mail.set_content(body, cte="quoted-printable") then I get Dear Dr. Bennett, Blorp! Bleep! -- Mailbot Inc. 010101 Bot Boulevard Botham City B=C3=B6tland That a bit better, but still not what I want since the main text could also be in German and thus also contain umlauts, etc. Cheers, Loris -- This signature is currently under construction. From jon+usenet at unequivocal.eu Mon Aug 23 07:06:47 2021 From: jon+usenet at unequivocal.eu (Jon Ribbens) Date: Mon, 23 Aug 2021 11:06:47 -0000 (UTC) Subject: Decoding of EmailMessage text References: <87wnocy17a.fsf@hornfels.zedat.fu-berlin.de> <87o89oxyzj.fsf@hornfels.zedat.fu-berlin.de> Message-ID: On 2021-08-23, Loris Bennett wrote: > If instead of > > mail.set_content(body) > > I do > > mail.set_content(body, cte="quoted-printable") Try print(mail.get_content()) rather than print(mail.as_string()) From loris.bennett at fu-berlin.de Mon Aug 23 07:12:57 2021 From: loris.bennett at fu-berlin.de (Loris Bennett) Date: Mon, 23 Aug 2021 13:12:57 +0200 Subject: Decoding of EmailMessage text References: <87wnocy17a.fsf@hornfels.zedat.fu-berlin.de> <87o89oxyzj.fsf@hornfels.zedat.fu-berlin.de> Message-ID: <87fsv0xvly.fsf@hornfels.zedat.fu-berlin.de> Jon Ribbens writes: > On 2021-08-23, Loris Bennett wrote: >> If instead of >> >> mail.set_content(body) >> >> I do >> >> mail.set_content(body, cte="quoted-printable") > > Try print(mail.get_content()) rather than print(mail.as_string()) That did the trick - thanks! Cheers, Loris -- This signature is currently under construction. From steevekerou at yahoo.fr Mon Aug 23 07:15:45 2021 From: steevekerou at yahoo.fr (Steeve Kerou) Date: Mon, 23 Aug 2021 11:15:45 +0000 (UTC) Subject: Why Pyto package not available yet ??? References: <2124684154.1365011.1629717345151.ref@mail.yahoo.com> Message-ID: <2124684154.1365011.1629717345151@mail.yahoo.com> Hi,? Here is Pyto, the first animated character that help you Learn Python like you play video games?Why not implement me on Python PyPI ??? Episode 1: Intro / Who is Pyto ? / The Idle World | Pytorial | | | | | | | | | | | Episode 1: Intro / Who is Pyto ? / The Idle World | Pytorial | | | Alan V. From janburse at fastmail.fm Mon Aug 23 13:53:31 2021 From: janburse at fastmail.fm (Mostowski Collapse) Date: Mon, 23 Aug 2021 19:53:31 +0200 Subject: ANN: Dogelog Runtime, Prolog to the Moon (2021) In-Reply-To: References: Message-ID: The world is getting ridiculous. termux seems to not anymore be supported by Google Play because of some Android 10 issues? On the other hand there is this gem: TI 84 Plus CE Python Edition Unboxing https://www.youtube.com/watch?v=LVxP_Fki8Fc LoL Mostowski Collapse schrieb: > Yesterday we went into a little programming binge, despite there > was a free parade in Zurich. We could now already implement a transpiler > that targets Python. We simply took the transpiler main.p that targets > > JavaScript and moded it into a new transpiler mainpy.p that targets > Python. The code is already on GitHub and we present it also here > as the Python code mainpy.p. We were also busy > > on machine.py and special.py. The progress is now: > > +------------+?? cross????? +-------------+ > | loader.p?? |?? compile??? | loader.py?? | 100% > | compiler.p | -----------> | compiler.py | 100% > +------------+????????????? +-------------+ > ??????????????????????????? | machine.py? |? 66% > ??????????????????????????? | special.py? |? 33% > ??????????????????????????? +-------------+ > > See also: > > Python Version of Dogelog Runtime special > https://twitter.com/dogelogch/status/1426884473988292617 > > Python Version of Dogelog Runtime special > https://www.facebook.com/groups/dogelog From wlfraed at ix.netcom.com Mon Aug 23 13:54:15 2021 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Mon, 23 Aug 2021 13:54:15 -0400 Subject: on perhaps unloading modules? References: <86k0kghtim.fsf@jevedi.com> <867dgfinp6.fsf@jevedi.com> <86a6lahoml.fsf@jevedi.com> <868s0uftbh.fsf@jevedi.com> <7st4ig986242i36gqemgr5e1kub6s8t6ld@4ax.com> <86o89p9t4j.fsf@jevedi.com> Message-ID: On Sun, 22 Aug 2021 16:28:12 -0300, Hope Rouselle declaimed the following: >That's wild. :-) Was this created by Brian Kernighan? It's hard to >believe. Oh, I think he wrote AMPL, wasn't it? A Mathematical >Programming Language, or something like that. Kenneth Iverson, early 1960s for release, though he started in the late 50s (so a decade before Kernighan). I believe it started life as a notation for publishing reports, not as an actual implemented language. {Hmmm, supposed to have influenced Matlab, S, and Wolfram/Mathematica} One of the quirks is that one reads APL from right to left... cf: You do not want to look down at the one-liner for Conway's Game of Life. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From george at fischhof.hu Mon Aug 23 16:08:27 2021 From: george at fischhof.hu (George Fischhof) Date: Mon, 23 Aug 2021 22:08:27 +0200 Subject: Making command-line args available to deeply-nested functions In-Reply-To: <87sfz0y0gx.fsf@hornfels.zedat.fu-berlin.de> References: <87czq8tpay.fsf@hornfels.zedat.fu-berlin.de> <230149ee-f6ed-4e2f-8ac3-c12388ca45acn@googlegroups.com> <878s0wtljf.fsf@hornfels.zedat.fu-berlin.de> <87sfz0y0gx.fsf@hornfels.zedat.fu-berlin.de> Message-ID: Loris Bennett ezt ?rta (id?pont: 2021. aug. 23., H 19:26): > George Fischhof writes: > > > Loris Bennett ezt ?rta (id?pont: 2021. aug. > > 20., P 17:54): > > > >> Julio Di Egidio writes: > >> > >> > On Friday, 20 August 2021 at 11:54:00 UTC+2, Loris Bennett wrote: > >> >> Hi, > >> >> > >> >> TL;DR: > >> >> > >> >> If I have a command-line argument for a program, what is the best way > >> >> of making this available to a deeply-nested[1] function call without > >> >> passing the parameter through every intermediate function? > >> > > >> > To not pass arguments you need shared state ("global variables"): and > >> > options in shard state, unless you have very good reasons to do > >> > otherwise, is simply a no no. > >> > >> Doesn't that slightly depend on the size of your "globe"? If a program > >> does a few, in some sense unrelated things, and, say, only runs for a > >> few minutes, could you not decide to make a particular parameter global, > >> even though only one function needs it? In general, however, I would > >> also avoid this. > >> > >> > > >> >> I can see that the top-level could just create an object from a class > >> >> which encapsulates everything, but what if I want to keep the > salutation > >> >> generation separate, so that I can have a separate program which just > >> >> generates the salutation and print it to the terminal? > >> > > >> > Yes, that's basically the way to go: parse arguments into a structure > (an > >> > object) that contains all options/parameters then pass that down. > Next > >> level: > >> > some sections of your code may require a certain subset of those > >> options, some > >> > may require some other, so you would structure your options object in > >> > sub-objects for the various sets of correlated options, then rather > pass > >> just > >> > the sub-object(s) that are relevant to the section of code you are > >> calling. > >> > Variations are of course possible, anyway that's the basic idea. > >> > > >> > Also have a look at the "argparse" library, it does all the heavy > >> lifting for > >> > the parsing and creation of those objects, definitely advised for in > non > >> trivial > >> > cases: . > >> > >> I am already using 'argparse' ('configargparse' actually). What aspect > >> should I be looking at in order to produce "sub-objects"? > >> > >> >> I guess I am really asking how to avoid "passing through" arguments > to > >> >> functions which only need them to call other functions, so maybe the > >> >> answer is just to avoid nesting. > >> > > >> > No, you don't get rid of code structure just not to pass arguments to > >> > a function... Code may be poorly structured, but that's another > >> > story. > >> > >> As I am writing new code it is more a question of imposing structure, > >> rather than getting rid of structure. Unwritten code for a given > >> purpose obviously has some sort of structure with regards to, say, loops > >> and conditions, but I am less sure about the implications for how the > >> code should be nested. Another argument against deeply-nested functions > >> is the increased complexity of testing. > > [snip (15 lines)]> > > > Hi, > > > > Also you can give a try to click and / or typer packages. > > Putting args into environment variables can be a solution too > > All of these depends on several things: personal preferences, colleagues > / > > firm standards, the program, readability, variable accessibility (IDE > > support, auto completition) (env vars not supported by IDEs as they are > not > > part of code) > > Thanks for the pointers, although I have only just got my head around > argparse/configargparse, so click is something I might have a look at > for future project. > > However, the question of how to parse the arguments is somewhat separate > from that of how to pass (or not pass) the arguments around within a > program. > > Cheers, > > Loris > > -- > This signature is currently under construction. > -- > https://mail.python.org/mailman/listinfo/python-list > > > > Hi, I thought not just parsing, but the usage method: you add a decorator to the function where you want to use the parameters. This way you do not have to pass the value through the calling hierarchy. Note: typer is a newer package, it contains click and leverages command line parsing even more. BR, George From barry at barrys-emacs.org Mon Aug 23 18:25:15 2021 From: barry at barrys-emacs.org (Barry) Date: Mon, 23 Aug 2021 23:25:15 +0100 Subject: PyQt5 is not recognized from python 3.8 installation in python 3.10 In-Reply-To: References: Message-ID: <88C8C3AA-CE17-4A31-9883-54561DFDC018@barrys-emacs.org> > On 23 Aug 2021, at 00:00, Mats Wichmann wrote: > > ?On 8/22/21 7:04 AM, Mohsen Owzar wrote: >> Hi guys, >> I have on my laptop the python installation 3.8 and newly I installed newest version 3.10 as well on my laptop. >> Now I have two IDLEs for both of the installations. >> When I rund some *.py file, having PyQt5 module, on the 3.8 version, it works as before without any problems. >> But whenn I run the same file on IDLE with 3.10 installation, it crashes and says that PyQt5 is not known. >> I tried to install this package with"pip install pyqt5" or with "py -3 -m pip install pyqt5", it brings lots of error messages (long long) as the lines below (they are only the beginning of the messages): > > make sure you're getting the right Python by doing > > py -3.10 -m pip install pyqt5 > > (the fact you're getting the build error below indicates you _are_ getting the right one, but it's good to be explicit anyway, just so you're sure). > >> ================================================== >> C:\Users\Mohsen>py -3 -m pip install pyqt5 >> Collecting pyqt5 >> Using cached PyQt5-5.15.4.tar.gz (3.3 MB) >> Installing build dependencies ... done >> Getting requirements to build wheel ... done >> Preparing wheel metadata ... error >> ERROR: Command errored out with exit status 1: >> command: 'C:\Users\Mohsen\AppData\Local\Programs\Python\Python310\python.exe' 'C:\Users\Mohsen\AppData\Local\Programs\Python\Python310\lib\site-packages\pip\_vendor\pep517\in_process\_in_process.py' prepare_metadata_for_build_wheel 'C:\Users\Mohsen\AppData\Local\Temp\tmprax0esmt' >> cwd: C:\Users\Mohsen\AppData\Local\Temp\pip-install-wl_b58e9\pyqt5_1cbd1bab46fa4abaad34b55514561ce6 >> Complete output (33 lines): >> Querying qmake about your Qt installation... >> C:\Qt\4.7.4\bin\qmake.exe -query >> Traceback (most recent call last): >> File "C:\Users\Mohsen\AppData\Local\Programs\Python\Python310\lib\site-packages\pip\_vendor\pep517\in_process\_in_process.py", line 143, in prepare_metadata_for_build_wheel >> hook = backend.prepare_metadata_for_build_wheel >> AttributeError: module 'sipbuild.api' has no attribute 'prepare_metadata_for_build_wheel' > > Your problem here is that there's no released binary wheel for PyQt5, since Py 3.10 isn't released (there's been some recent chatter about encouraging projects to make builds for new Python versions available early, e.g. once a Python version hits release candidate state, but that's just that - chatter - for now). > > In theory your system should be able to build it, but my experience is that unless you're an active Python developer on Windows and already have the right working setup, it pretty much always fails. These are the perils of trying to use a pre-release... > > That error suggests there's something different going on than usual (which has to do with the MSVC compiler suite not being set up the way the package expects): there looks like a version mismatch - it looks like it's finding qmake for Qt4, not Qt5. Maybe you can make some progress by adjusting some paths? Only trivial C code extensions can be built on windows. And then only if you have the right MSVC tools installed. Most interesting extensions have dependencies only other software. Which means that you need to know how to build all the dependencies as well. For something as complex as PyQt5 you need to be a developer with reasonable experience to build it. Check on PyPI for the available versions and install one of them. Barry > > Many people go here to get early-access, albeit unofficial, binary wheels: > > https://www.lfd.uci.edu/~gohlke/pythonlibs > > Unfortunately, PyQt5 is not available from there (as listed in the section at the very bottom) > > > -- > https://mail.python.org/mailman/listinfo/python-list > From nospam at please.ty Mon Aug 23 18:54:40 2021 From: nospam at please.ty (jak) Date: Tue, 24 Aug 2021 00:54:40 +0200 Subject: Decoding of EmailMessage text References: <87wnocy17a.fsf@hornfels.zedat.fu-berlin.de> <87o89oxyzj.fsf@hornfels.zedat.fu-berlin.de> <87fsv0xvly.fsf@hornfels.zedat.fu-berlin.de> Message-ID: Il 23/08/2021 13:12, Loris Bennett ha scritto: > Jon Ribbens writes: > >> On 2021-08-23, Loris Bennett wrote: >>> If instead of >>> >>> mail.set_content(body) >>> >>> I do >>> >>> mail.set_content(body, cte="quoted-printable") >> >> Try print(mail.get_content()) rather than print(mail.as_string()) > > That did the trick - thanks! > > Cheers, > > Loris > If you also want to know about the text, then that is probably utf8 encoded and converted to base64: from base64 import b64decode coded=(b'RGVhciBEci4gQmVubmV0dCwKCkJsb3JwISBCbGVlcCEKCgotLQpNYWlsYm90IEl' b'uYy4KMDEwMTAxIEJvdCBCb3VsZXZhcmQKQm90aGFtIENpdHkKQsO2dGxhbmQK') uncoded = b64decode(coded).decode('utf8') print(uncoded) output: Dear Dr. Bennett, Blorp! Bleep! -- Mailbot Inc. 010101 Bot Boulevard Botham City B?tland From mohsen.owzar at gmail.com Tue Aug 24 01:06:44 2021 From: mohsen.owzar at gmail.com (Mohsen Owzar) Date: Mon, 23 Aug 2021 22:06:44 -0700 (PDT) Subject: PyQt5 is not recognized from python 3.8 installation in python 3.10 In-Reply-To: References: <88C8C3AA-CE17-4A31-9883-54561DFDC018@barrys-emacs.org> Message-ID: <98484d2a-359a-46f4-a813-4fbc3e999876n@googlegroups.com> Barry schrieb am Dienstag, 24. August 2021 um 00:25:38 UTC+2: > > On 23 Aug 2021, at 00:00, Mats Wichmann wrote: > > > > On 8/22/21 7:04 AM, Mohsen Owzar wrote: > >> Hi guys, > >> I have on my laptop the python installation 3.8 and newly I installed newest version 3.10 as well on my laptop. > >> Now I have two IDLEs for both of the installations. > >> When I rund some *.py file, having PyQt5 module, on the 3.8 version, it works as before without any problems. > >> But whenn I run the same file on IDLE with 3.10 installation, it crashes and says that PyQt5 is not known. > >> I tried to install this package with"pip install pyqt5" or with "py -3 -m pip install pyqt5", it brings lots of error messages (long long) as the lines below (they are only the beginning of the messages): > > > > make sure you're getting the right Python by doing > > > > py -3.10 -m pip install pyqt5 > > > > (the fact you're getting the build error below indicates you _are_ getting the right one, but it's good to be explicit anyway, just so you're sure). > > > >> ================================================== > >> C:\Users\Mohsen>py -3 -m pip install pyqt5 > >> Collecting pyqt5 > >> Using cached PyQt5-5.15.4.tar.gz (3.3 MB) > >> Installing build dependencies ... done > >> Getting requirements to build wheel ... done > >> Preparing wheel metadata ... error > >> ERROR: Command errored out with exit status 1: > >> command: 'C:\Users\Mohsen\AppData\Local\Programs\Python\Python310\python.exe' 'C:\Users\Mohsen\AppData\Local\Programs\Python\Python310\lib\site-packages\pip\_vendor\pep517\in_process\_in_process.py' prepare_metadata_for_build_wheel 'C:\Users\Mohsen\AppData\Local\Temp\tmprax0esmt' > >> cwd: C:\Users\Mohsen\AppData\Local\Temp\pip-install-wl_b58e9\pyqt5_1cbd1bab46fa4abaad34b55514561ce6 > >> Complete output (33 lines): > >> Querying qmake about your Qt installation... > >> C:\Qt\4.7.4\bin\qmake.exe -query > >> Traceback (most recent call last): > >> File "C:\Users\Mohsen\AppData\Local\Programs\Python\Python310\lib\site-packages\pip\_vendor\pep517\in_process\_in_process.py", line 143, in prepare_metadata_for_build_wheel > >> hook = backend.prepare_metadata_for_build_wheel > >> AttributeError: module 'sipbuild.api' has no attribute 'prepare_metadata_for_build_wheel' > > > > Your problem here is that there's no released binary wheel for PyQt5, since Py 3.10 isn't released (there's been some recent chatter about encouraging projects to make builds for new Python versions available early, e.g. once a Python version hits release candidate state, but that's just that - chatter - for now). > > > > In theory your system should be able to build it, but my experience is that unless you're an active Python developer on Windows and already have the right working setup, it pretty much always fails. These are the perils of trying to use a pre-release... > > > > That error suggests there's something different going on than usual (which has to do with the MSVC compiler suite not being set up the way the package expects): there looks like a version mismatch - it looks like it's finding qmake for Qt4, not Qt5. Maybe you can make some progress by adjusting some paths? > Only trivial C code extensions can be built on windows. > And then only if you have the right MSVC tools installed. > Most interesting extensions have dependencies only other software. > Which means that you need to know how to build all the dependencies as well. > > For something as complex as PyQt5 you need to be a developer with reasonable experience to build it. > > Check on PyPI for the available versions and install one of them. > > Barry > > > > Many people go here to get early-access, albeit unofficial, binary wheels: > > > > https://www.lfd.uci.edu/~gohlke/pythonlibs > > > > Unfortunately, PyQt5 is not available from there (as listed in the section at the very bottom) > > > > > > -- > > https://mail.python.org/mailman/listinfo/python-list > > Thanks a lot for your answers. That's true. I had a project which used Qt4.7, and I have still on my laptop. I have not so big knowledge about compiling and building stuff, so I have to get rid of 3.10 version. OK, then I try to remove Python 3.10 and to install 3.9.6. Best regards Mohsen From loris.bennett at fu-berlin.de Tue Aug 24 01:39:39 2021 From: loris.bennett at fu-berlin.de (Loris Bennett) Date: Tue, 24 Aug 2021 07:39:39 +0200 Subject: Decoding of EmailMessage text References: <87wnocy17a.fsf@hornfels.zedat.fu-berlin.de> <87o89oxyzj.fsf@hornfels.zedat.fu-berlin.de> <87fsv0xvly.fsf@hornfels.zedat.fu-berlin.de> Message-ID: <875yvv5rl0.fsf@hornfels.zedat.fu-berlin.de> jak writes: > Il 23/08/2021 13:12, Loris Bennett ha scritto: >> Jon Ribbens writes: >> >>> On 2021-08-23, Loris Bennett wrote: >>>> If instead of >>>> >>>> mail.set_content(body) >>>> >>>> I do >>>> >>>> mail.set_content(body, cte="quoted-printable") >>> >>> Try print(mail.get_content()) rather than print(mail.as_string()) >> >> That did the trick - thanks! >> >> Cheers, >> >> Loris >> > > > If you also want to know about the text, then that is probably utf8 > encoded and converted to base64: > > from base64 import b64decode > > coded=(b'RGVhciBEci4gQmVubmV0dCwKCkJsb3JwISBCbGVlcCEKCgotLQpNYWlsYm90IEl' > b'uYy4KMDEwMTAxIEJvdCBCb3VsZXZhcmQKQm90aGFtIENpdHkKQsO2dGxhbmQK') > > uncoded = b64decode(coded).decode('utf8') > print(uncoded) > > output: > > Dear Dr. Bennett, > > Blorp! Bleep! > > > -- > Mailbot Inc. > 010101 Bot Boulevard > Botham City > B?tland Thanks! I don't need that right now, but it's good to know which decoding hoop I would have to jump through, if I did. Cheers, Loris -- This signature is currently under construction. From npapoylias at gmail.com Tue Aug 24 15:29:56 2021 From: npapoylias at gmail.com (Nick Papoylias) Date: Tue, 24 Aug 2021 21:29:56 +0200 Subject: [OSys PL Labs] 3 UI/UX Research Engineer Positions for Progr. Languages and Tools (Remote) Message-ID: Dear colleagues, The newly founded PL (Programming Languages) research Group at OutSystems has a goal of exploring the UI/UX frontier of Programming Tools. We are looking for 3 UI/UX Research Engineers for Programming Languages & Tools (Remote) to join our group. Please forward to anyone you think might be interested by our call: Europe/EMEA: https://www.outsystems.com/careers/job-detail/8a7887a87acffd16017b1cedb4930469/ US/Americas: https://www.outsystems.com/careers/job-detail/8a7885a87b55f750017b7479ec9f365b/ India/APAC: https://www.outsystems.com/careers/job-detail/8a7883a97ad004d8017b1011897d76de/ Best Regards, Dr. Papoulias (@npapoylias ) *Director of Research **@OutSystems* ================================================== *If you consider yourself (or aspire to be) a UI/UX expert with programming experience that wants to: ?Boldly go where no programmer has gone before? don?t let any impostor syndrome stop you, apply to join us! What we are looking for in our research group -- first and foremost -- is explorers. Take a look at this short video to quickly learn more about OutSystems: https://youtu.be/0gx3hMMDOZI. * *Responsibilities:* ** Your base responsibility will be the development of research prototypes from an engineering perspective. Nevertheless, the research nature of these prototypes will almost always require you to either learn a new language, a new system or way of working. You will always be given time and guidance (bibliography, books and an engineering starting point) to do so. The director of the group will always be there to guide you with all aspects of your work.* ** Once this base responsibility is fulfilled your UI/UX experience and expertise will help us go even further. What can we add to a good prototype to bring aesthetics and usability to the mix ? What will make us smile every time we use it ?* ** When you become comfortable with the above responsibilities you can start proposing your own experiments to the team and guide our newest members through the whole R&D process.* ** Finally, according to the group?s needs you will be tasked to present our work to colleagues, internally or externally (to the wider industrial and academic community), participate in conferences, publications and in the general dissemination of our work.* From hjp-python at hjp.at Tue Aug 24 18:02:49 2021 From: hjp-python at hjp.at (Peter J. Holzer) Date: Wed, 25 Aug 2021 00:02:49 +0200 Subject: on perhaps unloading modules? In-Reply-To: <86o89p9t4j.fsf@jevedi.com> References: <867dgfinp6.fsf@jevedi.com> <86a6lahoml.fsf@jevedi.com> <868s0uftbh.fsf@jevedi.com> <7st4ig986242i36gqemgr5e1kub6s8t6ld@4ax.com> <86o89p9t4j.fsf@jevedi.com> Message-ID: <20210824220249.GA5110@hjp.at> On 2021-08-22 16:28:12 -0300, Hope Rouselle wrote: > I have a certain distaste for syntax too. For instance, I would much > rather write and read ``first(ls)'' than ``ls[0]''. Would you also prefer `twothousandthreehundredandtwentythird(ls)` over `ls[2322]`? hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From iam at emirgecir.com.tr Tue Aug 24 18:30:11 2021 From: iam at emirgecir.com.tr (=?utf-8?B?RW1pciBHZcOnaXI=?=) Date: Wed, 25 Aug 2021 01:30:11 +0300 Subject: [Off-Topic?] I love Python Message-ID: <114991629843766@mail.yandex.com> I really love Python, it has an easy to understand and write syntax, it can get EVERY task done when used right and has a great community on platforms like Reddit, Discord etc. ** All the work every contributor, especially Guido and Mark Hammond has put into this language over years that is even longer than my lifespan is incredible, the endless list of modules by contributors, all the open source even non-open source projects done with Python is incredible. ** And since Python 3.10 exists Python 4 seems very far away but only time may show what will happen. Maybe even a bigger community, even children and elderly being able to make stuff. From rosuav at gmail.com Wed Aug 25 03:31:21 2021 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 25 Aug 2021 17:31:21 +1000 Subject: basic auth request In-Reply-To: <9A793671-1390-4CD6-914E-3D891225D2BC@barrys-emacs.org> References: <54465DA0-2977-4EAD-8CD2-C398F5ACF121@barrys-emacs.org> <9bc605cb-2ceb-fed9-cd3f-d48a8fe405fb@everest.reportlab.co.uk> <20210821185411.ka66xkawv6mbpska@gmail.com> <20210822084341.GA13245@hjp.at> <6ED57509-8AEA-4370-86ED-9F9ED04CA719@barrys-emacs.org> <9A793671-1390-4CD6-914E-3D891225D2BC@barrys-emacs.org> Message-ID: On Wed, Aug 25, 2021 at 5:20 PM Barry Scott wrote: > > Only if this threat model matters to you or your organisation. > Personal its low down of the threats I watch out for. > > The on-line world and the real-world are the same here. > > If a business changes hands then do you trust the new owners? > > Nothing we do with PKI certificates will answer that question. Fair enough; but a closer parallel would be walking up to a previously-familiar street vendor and seeing a different person there. Did the business change hands, or did some random dude hop over the counter and pretend to be a new owner? But you're right, it's not usually a particularly high risk threat. Still, it does further weaken the value of named SSL certificates and certificate authorities; there's not actually that much difference if the server just gave you a self-signed cert. In theory, the CA is supposed to protect you against someone doing a DNS hack and substituting a different server, in practice, anyone capable of doing a large-scale DNS hack is probably capable of getting a very legit-looking SSL cert for the name as well. ChrisA From jon+usenet at unequivocal.eu Wed Aug 25 06:59:45 2021 From: jon+usenet at unequivocal.eu (Jon Ribbens) Date: Wed, 25 Aug 2021 10:59:45 -0000 (UTC) Subject: basic auth request References: <54465DA0-2977-4EAD-8CD2-C398F5ACF121@barrys-emacs.org> <9bc605cb-2ceb-fed9-cd3f-d48a8fe405fb@everest.reportlab.co.uk> <20210821185411.ka66xkawv6mbpska@gmail.com> <20210822084341.GA13245@hjp.at> <6ED57509-8AEA-4370-86ED-9F9ED04CA719@barrys-emacs.org> <9A793671-1390-4CD6-914E-3D891225D2BC@barrys-emacs.org> Message-ID: On 2021-08-25, Chris Angelico wrote: > On Wed, Aug 25, 2021 at 5:20 PM Barry Scott wrote: >> Only if this threat model matters to you or your organisation. >> Personal its low down of the threats I watch out for. >> >> The on-line world and the real-world are the same here. >> >> If a business changes hands then do you trust the new owners? >> >> Nothing we do with PKI certificates will answer that question. > > Fair enough; but a closer parallel would be walking up to a > previously-familiar street vendor and seeing a different person there. > Did the business change hands, or did some random dude hop over the > counter and pretend to be a new owner? > > But you're right, it's not usually a particularly high risk threat. > Still, it does further weaken the value of named SSL certificates and > certificate authorities; there's not actually that much difference if > the server just gave you a self-signed cert. In theory, the CA is > supposed to protect you against someone doing a DNS hack and > substituting a different server, in practice, anyone capable of doing > a large-scale DNS hack is probably capable of getting a very > legit-looking SSL cert for the name as well. There are so many trusted CAs these days that the chances of them all being secure approaches zero - they are not all equal yet they are all equally trusted. Which is why a change of CA on a site you have visited before is potentially suspicious. From barry at barrys-emacs.org Wed Aug 25 03:20:13 2021 From: barry at barrys-emacs.org (Barry Scott) Date: Wed, 25 Aug 2021 08:20:13 +0100 Subject: basic auth request In-Reply-To: References: <54465DA0-2977-4EAD-8CD2-C398F5ACF121@barrys-emacs.org> <9bc605cb-2ceb-fed9-cd3f-d48a8fe405fb@everest.reportlab.co.uk> <20210821185411.ka66xkawv6mbpska@gmail.com> <20210822084341.GA13245@hjp.at> <6ED57509-8AEA-4370-86ED-9F9ED04CA719@barrys-emacs.org> Message-ID: <9A793671-1390-4CD6-914E-3D891225D2BC@barrys-emacs.org> > On 22 Aug 2021, at 12:03, Chris Angelico wrote: > > On Sun, Aug 22, 2021 at 8:30 PM Barry Scott > wrote: >> >> >> >> On 22 Aug 2021, at 10:37, Chris Angelico wrote: >> >> When it comes to security, one thing I'm very curious about is why we >> don't have any sort of certificate renewal verification. My browser >> could retain the certificates of some web site (or of all web sites, >> even - they're not THAT large), and if the site presents a different >> cert, it could show the previously retained one and challenge the >> server "prove that you're the same guy". This proof would consist of >> the latest cert, signed by the older cert's key (or possibly a chain >> that can construct such a proof, which would allow the server to >> simply retain each new cert signed by the one previous cert, forming a >> line - or a tree if necessary). My suspicion is that it'd add little >> above simply having a valid cert, but if people are paranoid, surely >> that's a better place to look? >> >> >> The web site proves it owners the hostname and/or IP address using its certificate. >> You use your trust store to show that you can trust that certificate. >> >> The fact that a certificate changes is not a reason to stop trusting a site. >> >> So it does not add anything. >> >> The pain point in PKI is revocation. The gold standard is for a web site to use OCSP stapling. >> But that is rare sadly. And because of issues with revocation lists, (privacy, latency, need to >> fail open on failiure, DoD vector, etc) this is where the paranoid should look. >> > > Fair point. Let me give you a bit of context. > > Recently, the owner/operator of a site (I'll call it > https://demo.example/ ) died. Other people, who have been using the > site extensively, wish for it to continue. If the domain registration > expires, anyone can reregister it, and can then generate a completely > new certificate for the common name "demo.example", and web browsers > will accept that. The old cert may or may not have expired, but it > won't be revoked. > > As far as I can tell, a web browser with default settings will happily > accept the change of ownership. It won't care that the IP address, > certificate, etc, have all changed. It just acknowledges that some CA > has signed some certificate with the right common name. And therein is > the vulnerability. (NOTE: I'm not saying that this is a real and > practical vulnerability - this is theoretical only, and a focus for > the paranoid.) > > This is true even if the old cert were one of those enhanced > certificates that some CAs try to upsell you to ("Extended Validation" > and friends). Even if, in the past, your bank was secured by one of > those certs, your browser will still accept a perfectly standard cert > next time. Which, in my opinion, renders those (quite pricey) > certificates no more secure than something from Let's Encrypt that has > no validation beyond ownership of DNS. > > Of course, you can pin a certificate. You can ask your browser to warn > you if it's changed *at all*. But since certs expire, that's highly > impractical, hence wondering why we don't have a system for using the > old cert to prove ownership of the new one. > > So how is a web browser supposed to distinguish between (a) normal > operation in which certs expire and are replaced, and (b) legit or > non-legit ownership changes? (Of course the browser can't tell you > whether the ownership change is legit, but out-of-band info can help > with that.) > > Or does it really matter that little? Only if this threat model matters to you or your organisation. Personal its low down of the threats I watch out for. The on-line world and the real-world are the same here. If a business changes hands then do you trust the new owners? Nothing we do with PKI certificates will answer that question. For web sites that we care a lot about, like banks, we trust that the site owners take care to protect that site. This includes making sure that they do not lose control of its DNS name and certificates. One of the biggest issues for PKI in recent years has been Certificate Authorities (CA) that issued certificates for web sites without checking that ownership. In these cases it lead to the browsers removing those CA's from the trust stores and also putting extra rules on all CA's to do a higher quality job. Barry > > ChrisA > -- > https://mail.python.org/mailman/listinfo/python-list From rosuav at gmail.com Wed Aug 25 10:19:07 2021 From: rosuav at gmail.com (Chris Angelico) Date: Thu, 26 Aug 2021 00:19:07 +1000 Subject: basic auth request In-Reply-To: References: <54465DA0-2977-4EAD-8CD2-C398F5ACF121@barrys-emacs.org> <9bc605cb-2ceb-fed9-cd3f-d48a8fe405fb@everest.reportlab.co.uk> <20210821185411.ka66xkawv6mbpska@gmail.com> <20210822084341.GA13245@hjp.at> <6ED57509-8AEA-4370-86ED-9F9ED04CA719@barrys-emacs.org> <9A793671-1390-4CD6-914E-3D891225D2BC@barrys-emacs.org> Message-ID: On Thu, Aug 26, 2021 at 12:16 AM Jon Ribbens via Python-list wrote: > > On 2021-08-25, Chris Angelico wrote: > > On Wed, Aug 25, 2021 at 5:20 PM Barry Scott wrote: > >> Only if this threat model matters to you or your organisation. > >> Personal its low down of the threats I watch out for. > >> > >> The on-line world and the real-world are the same here. > >> > >> If a business changes hands then do you trust the new owners? > >> > >> Nothing we do with PKI certificates will answer that question. > > > > Fair enough; but a closer parallel would be walking up to a > > previously-familiar street vendor and seeing a different person there. > > Did the business change hands, or did some random dude hop over the > > counter and pretend to be a new owner? > > > > But you're right, it's not usually a particularly high risk threat. > > Still, it does further weaken the value of named SSL certificates and > > certificate authorities; there's not actually that much difference if > > the server just gave you a self-signed cert. In theory, the CA is > > supposed to protect you against someone doing a DNS hack and > > substituting a different server, in practice, anyone capable of doing > > a large-scale DNS hack is probably capable of getting a very > > legit-looking SSL cert for the name as well. > > There are so many trusted CAs these days that the chances of them all > being secure approaches zero - they are not all equal yet they are all > equally trusted. Which is why a change of CA on a site you have visited > before is potentially suspicious. Do any popular web browsers notify you if that happens? I've certainly never noticed it with any that I use (and I've transitioned several sites from one CA to another). I've come to the conclusion that most security threats don't bother most people, and that security *warnings* bother nearly everyone, so real authentication of servers doesn't really matter all that much. *Encryption* does still have value, but you'd get that with a self-signed cert too. ChrisA From jon+usenet at unequivocal.eu Wed Aug 25 10:35:50 2021 From: jon+usenet at unequivocal.eu (Jon Ribbens) Date: Wed, 25 Aug 2021 14:35:50 -0000 (UTC) Subject: basic auth request References: <9bc605cb-2ceb-fed9-cd3f-d48a8fe405fb@everest.reportlab.co.uk> <20210821185411.ka66xkawv6mbpska@gmail.com> <20210822084341.GA13245@hjp.at> <6ED57509-8AEA-4370-86ED-9F9ED04CA719@barrys-emacs.org> <9A793671-1390-4CD6-914E-3D891225D2BC@barrys-emacs.org> Message-ID: On 2021-08-25, Chris Angelico wrote: > On Thu, Aug 26, 2021 at 12:16 AM Jon Ribbens via Python-list > wrote: >> There are so many trusted CAs these days that the chances of them all >> being secure approaches zero - they are not all equal yet they are all >> equally trusted. Which is why a change of CA on a site you have visited >> before is potentially suspicious. > > Do any popular web browsers notify you if that happens? I've certainly > never noticed it with any that I use (and I've transitioned several > sites from one CA to another). There was, if the site was using "HTTP Public Key Pinning". But that appears to have now been removed in favour of "Certificate Transparency", which to me seems to be a system very much based on the "problem: horse gone; solution: shut stable door" principle. Another attempt at combatting this problem is DNS CAA records, which are a way of politely asking all CAs in the world except the ones you choose "please don't issue a certificate for my domain". By definition someone who had hacked a CA would pay no attention to that request, of course. > I've come to the conclusion that most security threats don't bother > most people, and that security *warnings* bother nearly everyone, so > real authentication of servers doesn't really matter all that much. > *Encryption* does still have value, but you'd get that with a > self-signed cert too. Encryption without knowing who you're encrypting *to* is worthless, it's pretty much functionally equivalent to not encrypting. From rosuav at gmail.com Wed Aug 25 11:06:01 2021 From: rosuav at gmail.com (Chris Angelico) Date: Thu, 26 Aug 2021 01:06:01 +1000 Subject: basic auth request In-Reply-To: References: <9bc605cb-2ceb-fed9-cd3f-d48a8fe405fb@everest.reportlab.co.uk> <20210821185411.ka66xkawv6mbpska@gmail.com> <20210822084341.GA13245@hjp.at> <6ED57509-8AEA-4370-86ED-9F9ED04CA719@barrys-emacs.org> <9A793671-1390-4CD6-914E-3D891225D2BC@barrys-emacs.org> Message-ID: On Thu, Aug 26, 2021 at 12:48 AM Jon Ribbens via Python-list wrote: > > On 2021-08-25, Chris Angelico wrote: > > On Thu, Aug 26, 2021 at 12:16 AM Jon Ribbens via Python-list > > wrote: > >> There are so many trusted CAs these days that the chances of them all > >> being secure approaches zero - they are not all equal yet they are all > >> equally trusted. Which is why a change of CA on a site you have visited > >> before is potentially suspicious. > > > > Do any popular web browsers notify you if that happens? I've certainly > > never noticed it with any that I use (and I've transitioned several > > sites from one CA to another). > > There was, if the site was using "HTTP Public Key Pinning". But > that appears to have now been removed in favour of "Certificate > Transparency", which to me seems to be a system very much based > on the "problem: horse gone; solution: shut stable door" principle. > > Another attempt at combatting this problem is DNS CAA records, > which are a way of politely asking all CAs in the world except the > ones you choose "please don't issue a certificate for my domain". > By definition someone who had hacked a CA would pay no attention > to that request, of course. True, but that would still prevent legit CAs from unwittingly contributing to an attack. But it still wouldn't help if someone can do any sort of large-scale DNS attack, which is kinda essential for most of this to matter anyway (it doesn't matter if an attacker has a fake cert if all traffic goes to the legit site anyway). > > I've come to the conclusion that most security threats don't bother > > most people, and that security *warnings* bother nearly everyone, so > > real authentication of servers doesn't really matter all that much. > > *Encryption* does still have value, but you'd get that with a > > self-signed cert too. > > Encryption without knowing who you're encrypting *to* is worthless, > it's pretty much functionally equivalent to not encrypting. Somewhat. It does prevent various forms of MitM attack. It's all about adding extra difficulties on an attacker, so I wouldn't say "worthless", just because it isn't 100% reliable. Earlier I posited a hypothetical approach wherein the server would sign a new cert using the old cert, and would then be able to present that upon request. Are there any massive glaring problems with that? (Actually, I'm pretty sure there will be. Lemme reword. What massive glaring problems can you see with that?) It would require servers to retain a chain of certificates, and to be able to provide that upon request. It wouldn't even need a change to HTTP per se - could be something like "https://your.host.example/cert_proof.txt" the same way that robots.txt is done. In theory, that would allow a client to, at the cost of retaining the one last-seen cert for each site, have confidence that the site is the same one that was previously seen. But, maybe we're just coming back to "it doesn't matter and nobody really cares". ChrisA From jon+usenet at unequivocal.eu Wed Aug 25 11:47:26 2021 From: jon+usenet at unequivocal.eu (Jon Ribbens) Date: Wed, 25 Aug 2021 15:47:26 -0000 (UTC) Subject: basic auth request References: <20210821185411.ka66xkawv6mbpska@gmail.com> <20210822084341.GA13245@hjp.at> <6ED57509-8AEA-4370-86ED-9F9ED04CA719@barrys-emacs.org> <9A793671-1390-4CD6-914E-3D891225D2BC@barrys-emacs.org> Message-ID: On 2021-08-25, Chris Angelico wrote: > On Thu, Aug 26, 2021 at 12:48 AM Jon Ribbens via Python-list > wrote: >> Another attempt at combatting this problem is DNS CAA records, >> which are a way of politely asking all CAs in the world except the >> ones you choose "please don't issue a certificate for my domain". >> By definition someone who had hacked a CA would pay no attention >> to that request, of course. > > True, but that would still prevent legit CAs from unwittingly > contributing to an attack. But it still wouldn't help if someone can > do any sort of large-scale DNS attack, which is kinda essential for > most of this to matter anyway (it doesn't matter if an attacker has a > fake cert if all traffic goes to the legit site anyway). That depends whether it's a large-scale attack or targeted at some particular person or organisation, I suppose. > Earlier I posited a hypothetical approach wherein the server would > sign a new cert using the old cert, and would then be able to present > that upon request. Are there any massive glaring problems with that? That's a very similar idea to HTTP Public Key Pinning, and apparently there were enough problems with that that they discontinued it. > But, maybe we're just coming back to "it doesn't matter and nobody > really cares". People don't care until something goes wrong, and then suddenly they care a great deal... From hjp-python at hjp.at Wed Aug 25 13:01:19 2021 From: hjp-python at hjp.at (Peter J. Holzer) Date: Wed, 25 Aug 2021 19:01:19 +0200 Subject: basic auth request In-Reply-To: References: <54465DA0-2977-4EAD-8CD2-C398F5ACF121@barrys-emacs.org> <9bc605cb-2ceb-fed9-cd3f-d48a8fe405fb@everest.reportlab.co.uk> <20210821185411.ka66xkawv6mbpska@gmail.com> <20210822084341.GA13245@hjp.at> Message-ID: <20210825170119.GB5110@hjp.at> On 2021-08-22 19:37:24 +1000, Chris Angelico wrote: > On Sun, Aug 22, 2021 at 6:45 PM Peter J. Holzer wrote: > > > > On 2021-08-22 05:04:43 +1000, Chris Angelico wrote: > > > On Sun, Aug 22, 2021 at 4:55 AM Martin Di Paola > > > wrote: > > > > HTTPS ensures encryption so the content, including the Basic Auth > > > > username and password, is secret for any external observer. > > > > > > > > But it is *not* secret for the receiver (the server): if it was > > > > compromised an adversary will have access to your password. It is much > > > > easier to print a captured password than cracking the hashes. > > > > > > > > Other authentication mechanisms exist, like OAuth, which are more > > > > "secure". > > > > OAuth is "an /authorization protocol/, rather than an /authentication > > protocol/" [Wikipedia]. > > > > > If your server is compromised in that way, *all is lost*. > > > > If "you" are the service provider, yes. but if "you" are the user, no. > > If "your server" is compromised, then you are the service provider, > are you not? I'm not sure what "your server" would mean if "you" are > the user. The server you use. The same way you talk about "your bank" or "your school" etc. But that's besides the point. What I wanted to point out is that as a service provider you take some responsibility for the user's data and should take the user's POV into account. > > there are three levels of security (from highest > > to lowest) in this scenario: > > > > 1: The secret known to the user is never transmitted to the server at > > all, the client only proves that the secret is known. This is the > > case for TLS client authentication (which AFAIK all browsers support > > but is a real pain in the ass to set up, so it's basically never > > used) and for SCRAM (which isn't part of HTTP(S) but could be > > implemented in JavaScript). > > This would be great, if nobody minded (a) setting up a unique client > certificate for every site, or (b) allowing the ultimate in remote > tracking cookie whereby any server could recognize you by your TLS > certificate. Which is one of reasons why TLS client authentication wasn't really practical. It doesn't apply to SCRAM. > > So given the choice between Basic Auth and Digest or NTLM (over HTTPS in > > all cases) I would prefer Basic Auth. Ideally I would use SCRAM or a > > public key method, but I admit that my security requirements were never > > high enough to actually bother to do that (actually, I used SSL client > > side auth once, 20 years ago, ...). > > > > I would, of course, prefer something like form fill-out over Basic, > but that's due to UI concerns rather than security ones. Me too. But since that is irrelevant from a security POV I chose not to complicate matters by bringing that up. > When it comes to security, one thing I'm very curious about is why we > don't have any sort of certificate renewal verification. My browser > could retain the certificates of some web site (or of all web sites, > even - they're not THAT large), and if the site presents a different > cert, it could show the previously retained one and challenge the > server "prove that you're the same guy". This proof would consist of > the latest cert, signed by the older cert's key (or possibly a chain > that can construct such a proof, which would allow the server to > simply retain each new cert signed by the one previous cert, forming a > line - or a tree if necessary). I think this wasn't done because it violated the strictly hierarchical model of X.509, where CAs are fully trusted and the server operators aren't trusted at all. Letting them add signatures smacked too much of an egalitarian web of trust. Of course, technically, these days website certificates do form a web of trust (with multiple chains and CA cross-signing), but the mental model is still the same (and web site keys cannot be used for signing). Apart from that I can see two problems: The first is that if the private key is compromised, an attacker can use it to sign their own successor key. The second is that if the private key is lost, a successor key cannot be signed. So the absence or presence of such a signature is just corroborating evidence, not proof. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From * at eli.users.panix.com Wed Aug 25 13:41:41 2021 From: * at eli.users.panix.com (Eli the Bearded) Date: Wed, 25 Aug 2021 17:41:41 -0000 (UTC) Subject: basic auth request References: Message-ID: In comp.lang.python, Jon Ribbens wrote: > Another attempt at combatting this problem is DNS CAA records, > which are a way of politely asking all CAs in the world except the > ones you choose "please don't issue a certificate for my domain". > By definition someone who had hacked a CA would pay no attention > to that request, of course. Yeah, but it works for the case of forgotten hostnames, a rare but real attack. Basically it works like this: $COMPANY puts out a lot of things on different IP addresses from a shared public(ish) pool like AWS and assigns different names to them. Later $COMPANY discontinues one or more of those things, terminates the host, and lets the IP address rejoin the public(ish) pool. $ATTACKER notices the domain name pointing to an unused IP address and works to acquire it for their own server. $ATTACKER then gets a cert for that domain, since they can easily prove ownership of the server through http content challenges. $ATTACKER now has a host in $COMPANY's name to launch phishing attacks. This probably has some clever infosec name that I don't know. Elijah ------ or a clever infosec name now forgotten From jon+usenet at unequivocal.eu Wed Aug 25 15:06:38 2021 From: jon+usenet at unequivocal.eu (Jon Ribbens) Date: Wed, 25 Aug 2021 19:06:38 -0000 (UTC) Subject: basic auth request References: Message-ID: On 2021-08-25, Eli the Bearded <*@eli.users.panix.com> wrote: > In comp.lang.python, Jon Ribbens wrote: >> Another attempt at combatting this problem is DNS CAA records, >> which are a way of politely asking all CAs in the world except the >> ones you choose "please don't issue a certificate for my domain". >> By definition someone who had hacked a CA would pay no attention >> to that request, of course. > > Yeah, but it works for the case of forgotten hostnames, a rare but > real attack. Basically it works like this: > > $COMPANY puts out a lot of things on different IP addresses from > a shared public(ish) pool like AWS and assigns different names > to them. Later $COMPANY discontinues one or more of those things, > terminates the host, and lets the IP address rejoin the public(ish) > pool. > > $ATTACKER notices the domain name pointing to an unused IP address > and works to acquire it for their own server. $ATTACKER then gets > a cert for that domain, since they can easily prove ownership of > the server through http content challenges. $ATTACKER now has a > host in $COMPANY's name to launch phishing attacks. How does CAA help with this? Unless the domain owner knows in advance that they're going to forget about the hostname and prepares for it by setting a CAA record that denies all CAs, the attacker will simply get a certificate from one of the permitted CAs - since, as you point out, they genuinely own and control the relevant IP address. From * at eli.users.panix.com Wed Aug 25 16:19:55 2021 From: * at eli.users.panix.com (Eli the Bearded) Date: Wed, 25 Aug 2021 20:19:55 -0000 (UTC) Subject: basic auth request References: Message-ID: In comp.lang.python, Jon Ribbens wrote: > On 2021-08-25, Eli the Bearded <*@eli.users.panix.com> wrote: >> $COMPANY puts out a lot of things on different IP addresses from >> a shared public(ish) pool like AWS and assigns different names >> to them. Later $COMPANY discontinues one or more of those things, >> terminates the host, and lets the IP address rejoin the public(ish) >> pool. >> >> $ATTACKER notices the domain name pointing to an unused IP address >> and works to acquire it for their own server. $ATTACKER then gets >> a cert for that domain, since they can easily prove ownership of >> the server through http content challenges. $ATTACKER now has a >> host in $COMPANY's name to launch phishing attacks. > How does CAA help with this? Unless the domain owner knows in advance > that they're going to forget about the hostname and prepares for it > by setting a CAA record that denies all CAs, the attacker will simply > get a certificate from one of the permitted CAs - since, as you point > out, they genuinely own and control the relevant IP address. I believe the way it helps is by limiting to a CA that will insist all cert requests come through the right channel, not some random one off somewhere. This doesn't prevent issues, but does raise the complexity on an already niche attack. It does aid in knocking out the easy random one-offs from Let's Encrypt. Elijah ------ using LE for all his personal sites these days From barry at barrys-emacs.org Wed Aug 25 19:09:30 2021 From: barry at barrys-emacs.org (Barry) Date: Thu, 26 Aug 2021 00:09:30 +0100 Subject: basic auth request In-Reply-To: References: Message-ID: <8B80609C-9D91-4DD5-9EB5-32C95BA500E1@barrys-emacs.org> > On 25 Aug 2021, at 20:34, Eli the Bearded <*@eli.users.panix.com> wrote: > > ?In comp.lang.python, Jon Ribbens wrote: >> Another attempt at combatting this problem is DNS CAA records, >> which are a way of politely asking all CAs in the world except the >> ones you choose "please don't issue a certificate for my domain". >> By definition someone who had hacked a CA would pay no attention >> to that request, of course. > > Yeah, but it works for the case of forgotten hostnames, a rare but > real attack. Basically it works like this: > > $COMPANY puts out a lot of things on different IP addresses from > a shared public(ish) pool like AWS and assigns different names > to them. Later $COMPANY discontinues one or more of those things, > terminates the host, and lets the IP address rejoin the public(ish) > pool. > > $ATTACKER notices the domain name pointing to an unused IP address > and works to acquire it for their own server. $ATTACKER then gets > a cert for that domain, since they can easily prove ownership of > the server through http content challenges. $ATTACKER now has a > host in $COMPANY's name to launch phishing attacks. > > This probably has some clever infosec name that I don't know. It is possible to sign an ip address in a certificate, but that is not often done. Getting to reuse the IP address that example.com was using will not help the attacker unless they can make a cert that signs the dns name. And that means they hacked the CA which is a big problem. Barry > > Elijah > ------ > or a clever infosec name now forgotten > > -- > https://mail.python.org/mailman/listinfo/python-list > From * at eli.users.panix.com Wed Aug 25 20:34:30 2021 From: * at eli.users.panix.com (Eli the Bearded) Date: Thu, 26 Aug 2021 00:34:30 -0000 (UTC) Subject: basic auth request References: <8B80609C-9D91-4DD5-9EB5-32C95BA500E1@barrys-emacs.org> Message-ID: In comp.lang.python, Barry wrote: > It is possible to sign an ip address in a certificate, but that is not > often done. It's bad practice. I've never seen one in the wild. > Getting to reuse the IP address that example.com was using will not help > the attacker unless they can make a cert that signs the dns name. > And that means they hacked the CA which is a big problem. You misunderstand the attack. Some web searching suggests the term is "dangling DNS record". Big co Acme Example, with example.com, has a website for the regular public on www.example.com, gets mail at mail.example.com, serves DNS from ns1., ns2. and ns3.example.com. The IT staff watch those domaines very carefully. One day marketing says, "We've got a big CES show this year, let's make a website for the press at ces.example.com." They tell execs the execs tell the IT guys the IT guys say "Okay, what does it point to?" and Marketing gives them the IP address of the blog site they just rented. IT sets up an A record. IT does not watch _that_ carefully. Two years later Marketing stops paying the bill on the blog site, and ces.example.com has a "dangling" DNS record, it exists but no longer points to a valid resource. Attacker gets the IP address that points to (maybe they churn through a bunch of temporary accounts until they do) and now with the right IP to match ces.example.com they go off to get a SSL cert for that. $500 bug bounty write up here for someone who found a dangling record, but didn't churn for the record to exploit it: https://gist.github.com/TheBinitGhimire/9ebcd27086a11df1d7ec925e5f604e03 Another variant of this, which probably doesn't get you an SSL cert, is a dangling CNAME. These can be easier to get. If ces.example.com was a CNAME to cesdemosite2017.com then when cesdemosite2017.com expires, it's trivial to re-register it and squat "as" ces.example.com. The most insidious version is a DNS delegation. If ces.example.com is an NS record (unlikely for a marketing site, but plausible for some other scenarios) and it goes to ns1.parternership.net, when parternership.net expires the attacker can grab that, create a new ns1.parternership.net and give themselves finan.ces.example.com then start spitting out bogus bills with it. The CAA record adds a smidgen more protection against those attacks. (I don't think that's what it is designed for, but a good defense works against more than just the original attack method.) I also found this in my search, which is exactly the sort of threat CAA was meant to handle: https://en.wikipedia.org/wiki/Comodo_Cybersecurity#Dangling_markup_injection_vulnerability On 25 July 2016, Matthew Bryant showed that Comodo's website is vulnerable to dangling markup injection attacks and can send emails to system administrators from Comodo's servers to approve a wildcard certificate issue request which can be used to issue arbitrary wildcard certificates via Comodo's 30-Day PositiveSSL product. Bugs in automated systems that give out arbitrary certs are not common, but very very nasty. Elijah ------ DNS: the cause of, and solution to, all our Internet problems From arj.python at gmail.com Thu Aug 26 03:09:21 2021 From: arj.python at gmail.com (Abdur-Rahmaan Janhangeer) Date: Thu, 26 Aug 2021 11:09:21 +0400 Subject: Pandas: Multiple CSVs in one Zip file Message-ID: Greetings, Cannot read one file in a zip file if the zip file contains multiple files. This example does not work https://www.py4u.net/discuss/203494 as Pandas shows a ValueError: Multiple files found in ZIP file. Only one file per ZIP. If the Zip file has one file, fine else i cannot find a way. Thanks Kind Regards, Abdur-Rahmaan Janhangeer about | blog github Mauritius From __peter__ at web.de Thu Aug 26 03:38:38 2021 From: __peter__ at web.de (Peter Otten) Date: Thu, 26 Aug 2021 09:38:38 +0200 Subject: Pandas: Multiple CSVs in one Zip file In-Reply-To: References: Message-ID: On 26/08/2021 09:09, Abdur-Rahmaan Janhangeer wrote: > Cannot read one file in a zip file if the zip file contains multiple files. > > This example does not work https://www.py4u.net/discuss/203494 as Pandas > shows a ValueError: Multiple files found in ZIP file. Only one file per ZIP. > > If the Zip file has one file, fine else i cannot find a way. Thanks You may have introduced an error when you translated the snippet to your use case. What went wrong is hard to guess unless you provide the exact failing code. Pandas can read a single zipped file out of the box and the accepted answer in your indirect link to https://stackoverflow.com/questions/61971040/python-extract-csv-files-from-multiple-zip-files-and-combine-the-data shows how to deal with zip files containing multiple files. From hjp-python at hjp.at Thu Aug 26 05:59:34 2021 From: hjp-python at hjp.at (Peter J. Holzer) Date: Thu, 26 Aug 2021 11:59:34 +0200 Subject: Pandas: Multiple CSVs in one Zip file In-Reply-To: References: Message-ID: <20210826095934.GA24778@hjp.at> On 2021-08-26 11:09:21 +0400, Abdur-Rahmaan Janhangeer wrote: > Cannot read one file in a zip file if the zip file contains multiple files. > > This example does not work https://www.py4u.net/discuss/203494 as Pandas > shows a ValueError: Multiple files found in ZIP file. Only one file per ZIP. > > If the Zip file has one file, fine else i cannot find a way. Thanks Is it possible that you are trying to treat the zip file as a gzip file? Those are different file formats with different purposes (archive vs. stream), but they use the same compression algorithm, and the gzip tool (and - I presume - also the gzip library) can read a zip file with a single member. The error message would match that. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From loris.bennett at fu-berlin.de Thu Aug 26 05:51:08 2021 From: loris.bennett at fu-berlin.de (Loris Bennett) Date: Thu, 26 Aug 2021 11:51:08 +0200 Subject: Making command-line args available to deeply-nested functions References: <87czq8tpay.fsf@hornfels.zedat.fu-berlin.de> <230149ee-f6ed-4e2f-8ac3-c12388ca45acn@googlegroups.com> <878s0wtljf.fsf@hornfels.zedat.fu-berlin.de> <87sfz0y0gx.fsf@hornfels.zedat.fu-berlin.de> Message-ID: <87sfyw7cvn.fsf@hornfels.zedat.fu-berlin.de> George Fischhof writes: [snip (79 lines)] >> > Hi, >> > >> > Also you can give a try to click and / or typer packages. >> > Putting args into environment variables can be a solution too >> > All of these depends on several things: personal preferences, colleagues >> / >> > firm standards, the program, readability, variable accessibility (IDE >> > support, auto completition) (env vars not supported by IDEs as they are >> not >> > part of code) >> >> Thanks for the pointers, although I have only just got my head around >> argparse/configargparse, so click is something I might have a look at >> for future project. >> >> However, the question of how to parse the arguments is somewhat separate >> from that of how to pass (or not pass) the arguments around within a >> program. [snip (16 lines)] > > Hi, > I thought not just parsing, but the usage method: you add a decorator to > the function where you want to use the parameters. This way you do not have > to pass the value through the calling hierarchy. > > Note: typer is a newer package, it contains click and leverages command > line parsing even more. Do you have an example of how this is done? From a cursory reading of the documentation, it didn't seem obvious to me how to do this, but then I don't have much understanding of how decorators work. Cheers, Loris -- This signature is currently under construction. From loris.bennett at fu-berlin.de Thu Aug 26 06:01:41 2021 From: loris.bennett at fu-berlin.de (Loris Bennett) Date: Thu, 26 Aug 2021 12:01:41 +0200 Subject: configargparse - reading option from config only Message-ID: <87lf4o7ce2.fsf@hornfels.zedat.fu-berlin.de> Hi, When using configargparse, it seems that if a value is to be read from a config file, it also has to be defined as a command-line argument in order to turn up as an attribute in the parser namespace. I can sort of see why this is the case, but there are also some options I would like to read just from the config file and not have them available as command-line options. This would be, say, to prevent the number of options on the command-line from becoming bloated by little-used settings. Is there an elegant way to do this? Cheers, Loris -- This signature is currently under construction. From Gronicus at SGA.Ninja Thu Aug 26 11:47:41 2021 From: Gronicus at SGA.Ninja (Steve) Date: Thu, 26 Aug 2021 11:47:41 -0400 Subject: matplotlib questions Message-ID: <000801d79a91$b4d851d0$1e88f570$@SGA.Ninja> I am trying to modify the "Bar Graph Demo" at https://matplotlib.org/stable/gallery/index.html, Lines, bars, and markers but the more I experiment and change the code, the more messed up it becomes. I have the demo code working. This is my second attempt. I guess I accidentally got my first chart working but this second one, not so good. Is there any source to help me understand how the code works and how to change it? Among many others options, how do I change the font size? How are the labels placed on the X-axis and Y-axis? From janburse at fastmail.fm Thu Aug 26 15:01:40 2021 From: janburse at fastmail.fm (Mostowski Collapse) Date: Thu, 26 Aug 2021 21:01:40 +0200 Subject: ANN: Dogelog Runtime, Prolog to the Moon (2021) In-Reply-To: References: Message-ID: Having fun with a new attended query answerer for the Dogelog runtime. It can be bottled into a single Python file, no server roundtrip, just ISO core Prolog in one Python file, requires Python 3.10: >python.exe toplevel.py Dogelog Runtime, Prolog to the Moon, 0.9.3 (c) 1985-2021, XLOG Technologies AG, Switzerland ?- X=1; X=2. X = 1; X = 2. ?- X= ... ; X = ... . X = ...; X = ... . ?- So we adopted displaying a dot when there are no more choice points. This is seen in SWI-Prolog for example, but was also adopted by Scryer Prolog recently. Note the space between '...' and '.' in the last answer of the last query. This is needed so that what is shown is copyable. The query answerer is described here: Dogelog Runtime attended Prolog query answers. (Jekejeke) https://twitter.com/dogelogch/status/1430647215928877065 Dogelog Runtime attended Prolog query answers. (Jekejeke) https://www.facebook.com/groups/dogelog From mats at wichmann.us Thu Aug 26 14:10:49 2021 From: mats at wichmann.us (Mats Wichmann) Date: Thu, 26 Aug 2021 12:10:49 -0600 Subject: matplotlib questions In-Reply-To: <000801d79a91$b4d851d0$1e88f570$@SGA.Ninja> References: <000801d79a91$b4d851d0$1e88f570$@SGA.Ninja> Message-ID: <666c3b8d-4250-303b-b3ca-7d8271988495@wichmann.us> On 8/26/21 9:47 AM, Steve wrote: > I am trying to modify the "Bar Graph Demo" at > https://matplotlib.org/stable/gallery/index.html, Lines, bars, and markers > but the more I experiment and change the code, the more messed up it > becomes. I have the demo code working. This is my second attempt. I guess > I accidentally got my first chart working but this second one, not so good. > > Is there any source to help me understand how the code works and how to > change it? > Among many others options, how do I change the font size? > How are the labels placed on the X-axis and Y-axis? https://matplotlib.org/stable/api/matplotlib_configurations_api.html From kaiser.barbarossa at yandex.com Thu Aug 26 16:27:00 2021 From: kaiser.barbarossa at yandex.com (tuxifreund) Date: Thu, 26 Aug 2021 20:27:00 -0000 (UTC) Subject: configargparse - reading option from config only References: <87lf4o7ce2.fsf@hornfels.zedat.fu-berlin.de> Message-ID: Hello, you could use the argparse module[1] to parse command line arguments and configparser[2] to parse configuration files following the ini file structure. Is that what you are expecting? Cheers [1]: https://docs.python.org/3/library/argparse.html [2]: https://docs.python.org/3/library/configparser.html From Richard at Damon-Family.org Thu Aug 26 21:18:47 2021 From: Richard at Damon-Family.org (Richard Damon) Date: Thu, 26 Aug 2021 21:18:47 -0400 Subject: configargparse - reading option from config only In-Reply-To: <87lf4o7ce2.fsf@hornfels.zedat.fu-berlin.de> References: <87lf4o7ce2.fsf@hornfels.zedat.fu-berlin.de> Message-ID: On 8/26/21 6:01 AM, Loris Bennett wrote: > Hi, > > When using configargparse, it seems that if a value is to be read from a > config file, it also has to be defined as a command-line argument in > order to turn up as an attribute in the parser namespace. > > I can sort of see why this is the case, but there are also some options > I would like to read just from the config file and not have them > available as command-line options. This would be, say, to prevent the > number of options on the command-line from becoming bloated by > little-used settings. > > Is there an elegant way to do this? > > Cheers, > > Loris > Look at the read() member function to supply the file name to read. Then in the config object there will be sections for each section in the config file. No need for any of these to be 'options' -- Richard Damon From loris.bennett at fu-berlin.de Fri Aug 27 03:37:42 2021 From: loris.bennett at fu-berlin.de (Loris Bennett) Date: Fri, 27 Aug 2021 09:37:42 +0200 Subject: configargparse - reading option from config only References: <87lf4o7ce2.fsf@hornfels.zedat.fu-berlin.de> Message-ID: <87mtp3jq2h.fsf@hornfels.zedat.fu-berlin.de> Richard Damon writes: > On 8/26/21 6:01 AM, Loris Bennett wrote: >> Hi, >> >> When using configargparse, it seems that if a value is to be read from a >> config file, it also has to be defined as a command-line argument in >> order to turn up as an attribute in the parser namespace. >> >> I can sort of see why this is the case, but there are also some options >> I would like to read just from the config file and not have them >> available as command-line options. This would be, say, to prevent the >> number of options on the command-line from becoming bloated by >> little-used settings. >> >> Is there an elegant way to do this? >> >> Cheers, >> >> Loris >> > Look at the read() member function to supply the file name to read. Then > in the config object there will be sections for each section in the > config file. No need for any of these to be 'options' Do you have a link for this? As far as I can see, the config files are given in the following manner: p = configargparse.ArgParser(default_config_files=['/etc/app/conf.d/*.conf', '~/.my_settings']) I can obviously just read the config file with configparser, but the idea of configargparse is that an option can be specified as an option, in a config file, or as an environment variable, As far as I can tell, configargparse only loads entries from the config file into the appropriate namespace if they have also been defined as long options (i.e. with '--'). I was hoping to access *all* the config file entries, regardless of whether they are also options, since the config is obviously being read. Cheers, Loris -- This signature is currently under construction. From loris.bennett at fu-berlin.de Fri Aug 27 03:40:45 2021 From: loris.bennett at fu-berlin.de (Loris Bennett) Date: Fri, 27 Aug 2021 09:40:45 +0200 Subject: configargparse - reading option from config only References: <87lf4o7ce2.fsf@hornfels.zedat.fu-berlin.de> Message-ID: <87ilzrjpxe.fsf@hornfels.zedat.fu-berlin.de> tuxifreund writes: > Hello, > > you could use the argparse module[1] to parse command line arguments and > configparser[2] to parse configuration files following the ini file > structure. Is that what you are expecting? I have used the combination of argparse and configparser before. However, I was hoping to just use configargparse instead. Cheers, Loris > > Cheers > > > [1]: https://docs.python.org/3/library/argparse.html > [2]: https://docs.python.org/3/library/configparser.html -- Dr. Loris Bennett (Hr./Mr.) ZEDAT, Freie Universit?t Berlin Email loris.bennett at fu-berlin.de From Joseph.Schachner at Teledyne.com Fri Aug 27 12:57:08 2021 From: Joseph.Schachner at Teledyne.com (Schachner, Joseph) Date: Fri, 27 Aug 2021 16:57:08 +0000 Subject: matplotlib questions In-Reply-To: <000801d79a91$b4d851d0$1e88f570$@SGA.Ninja> References: <000801d79a91$b4d851d0$1e88f570$@SGA.Ninja> Message-ID: Complete documentation link (this link works) : https://matplotlib.org/stable/contents.html --- Joseph S. Teledyne Confidential; Commercially Sensitive Business Data -----Original Message----- From: Steve Sent: Thursday, August 26, 2021 11:48 AM To: python-list at python.org Subject: matplotlib questions I am trying to modify the "Bar Graph Demo" at https://matplotlib.org/stable/gallery/index.html, Lines, bars, and markers but the more I experiment and change the code, the more messed up it becomes. I have the demo code working. This is my second attempt. I guess I accidentally got my first chart working but this second one, not so good. Is there any source to help me understand how the code works and how to change it? Among many others options, how do I change the font size? How are the labels placed on the X-axis and Y-axis? From rmlibre at riseup.net Fri Aug 27 13:35:09 2021 From: rmlibre at riseup.net (rmlibre at riseup.net) Date: Fri, 27 Aug 2021 10:35:09 -0700 Subject: sha3 internal state export & import Message-ID: The hashlib module's SHA3 functions (specifically, sha3_256 & sha3_512) are not able to be pickled as far as I'm able to see. I know that the internal state of a SHA3 object can be easily represented by two unique values, the 1600-bit `S`-state value, and the last, smaller than `r`-rate number of bits (1088 for sha3_256, and 576 for sha3_512) of data which have not yet been incorporated into the `S`-state. Is there a simple way to export these two internal values from a sha3_256 or sha3_512 object, and conversely, a simple way to import these two exported values back into a new object? The goal is to be able to pause a hash object, then to store the state for some later time at which a new object can be created that's functionally equivalent to the first. Is there a simple way to do this? Best, rmlibre From david at lowryduda.com Fri Aug 27 15:25:13 2021 From: david at lowryduda.com (David Lowry-Duda) Date: Fri, 27 Aug 2021 15:25:13 -0400 Subject: matplotlib questions In-Reply-To: <000801d79a91$b4d851d0$1e88f570$@SGA.Ninja> References: <000801d79a91$b4d851d0$1e88f570$@SGA.Ninja> Message-ID: > I am trying to modify the "Bar Graph Demo" at > https://matplotlib.org/stable/gallery/index.html, Lines, bars, and > markers > but the more I experiment and change the code, the more messed up it > becomes. It is much easier to give constructive suggestions if you give a minimum runnable code sample that indicates what you're trying and what you're trying to do. See also http://catb.org/~esr/faqs/smart-questions.html I'll also note that I see nothing called "bar graph demo" on the gallery page. - DLD From Richard at Damon-Family.org Fri Aug 27 20:06:24 2021 From: Richard at Damon-Family.org (Richard Damon) Date: Fri, 27 Aug 2021 20:06:24 -0400 Subject: configargparse - reading option from config only In-Reply-To: <87mtp3jq2h.fsf@hornfels.zedat.fu-berlin.de> References: <87lf4o7ce2.fsf@hornfels.zedat.fu-berlin.de> <87mtp3jq2h.fsf@hornfels.zedat.fu-berlin.de> Message-ID: <9976b879-98cd-5a2b-5394-e42923334948@Damon-Family.org> On 8/27/21 3:37 AM, Loris Bennett wrote: > Richard Damon writes: > >> On 8/26/21 6:01 AM, Loris Bennett wrote: >>> Hi, >>> >>> When using configargparse, it seems that if a value is to be read from a >>> config file, it also has to be defined as a command-line argument in >>> order to turn up as an attribute in the parser namespace. >>> >>> I can sort of see why this is the case, but there are also some options >>> I would like to read just from the config file and not have them >>> available as command-line options. This would be, say, to prevent the >>> number of options on the command-line from becoming bloated by >>> little-used settings. >>> >>> Is there an elegant way to do this? >>> >>> Cheers, >>> >>> Loris >>> >> Look at the read() member function to supply the file name to read. Then >> in the config object there will be sections for each section in the >> config file. No need for any of these to be 'options' > Do you have a link for this? As far as I can see, the config files are > given in the following manner: > > p = configargparse.ArgParser(default_config_files=['/etc/app/conf.d/*.conf', '~/.my_settings']) > > I can obviously just read the config file with configparser, but the > idea of configargparse is that an option can be specified as an option, > in a config file, or as an environment variable, > > As far as I can tell, configargparse only loads entries from the config > file into the appropriate namespace if they have also been defined as > long options (i.e. with '--'). I was hoping to access *all* the config > file entries, regardless of whether they are also options, since the > config is obviously being read. > > Cheers, > > Loris > I misread your question, I thought you were talking about configparse. Question is, if configargparse doesn't do what you want, then it isn't the right tool. It looks like configargparse is SPECIFICALLY designed to allow the use to use a file as a shorthand to present command line arguements. The whole parsing structure is based on an enumerated set of options, if that isn't what you have, it is the wrong tool. -- Richard Damon From Gronicus at SGA.Ninja Fri Aug 27 23:39:05 2021 From: Gronicus at SGA.Ninja (Steve) Date: Fri, 27 Aug 2021 23:39:05 -0400 Subject: matplotlib questions In-Reply-To: References: <000801d79a91$b4d851d0$1e88f570$@SGA.Ninja> Message-ID: <005c01d79bbe$410754d0$c315fe70$@SGA.Ninja> I would like to know how the data is placed on the Y-axis and at the tops of the bars. The data is not being shown properly. With some exceptions, it looks as if the data is getting sorted independently from the dates. OK, here is the code: ============================================== # https://matplotlib.org/stable/gallery/index.html import matplotlib.pyplot as plt import numpy as np width = 12 #Width of the graph height = 6 #Height of the graph plt.rcParams["figure.figsize"] = (width,height) plt.rcParams["font.size"] = (9.0) Count = 0 datesList = [] # Each date showing end of bottle use hoursList = [] # Number of hours # daysList = [] # Number of days calculated from hours/24 countList = [] # simple tally with open("__Insulin_Tracker.txt", 'r') as infile: for lineEQN in infile: insulinHours = lineEQN[47:52].strip() print("Hours = " + insulinHours) hoursList.append(insulinHours) insulinDates = lineEQN[20:30].strip() datesList.append(insulinDates) # insulinDays= lineEQN[57:62].strip() # daysList.append(insulinDays) Count += 1 countList.append(str(Count)) # print(" " + str(Count) + " " + insulinDates + " Hours: " + insulinHours) x = Count count = str(Count) # Each date indicated the date on which a bottle of insulin has been depleted # The bar is to show the number of hours that the bottle has been in use. Labels = datesList Xdata= hoursList Title = ("Bottle List Number of entries: " + count) x = np.arange(len(Labels)) # the label locations width = 0.35 # the width of the bars margin = 0 fig, ax = plt.subplots() fig.tight_layout(pad=10) # Sets the size of the graph rects1 = ax.bar(x - width/2, Xdata, width, label='Hours') #Populates the x axis # Add some text for labels, title and custom x-axis tick labels, etc. # fontsize = 20 ax.set_ylabel('Hours of use for each bottle') ax.set_title(Title) ax.set_xticks(x) ax.set_xticklabels((datesList), rotation = 90) #Dates at bottom of the graph ax.legend() ax.bar_label(rects1, padding=0,rotation = 90) plt.show() =================================== Here is my data in __Insulin_Tracker.txt (with indents) =================================== Sat Jan 02, 2021 15 29 1.21 Thu Jan 07, 2021 01 116 4.83 Tue Jan 12, 2021 01 120 5.00 Fri Jan 15, 2021 23 74 3.08 Tue Jan 19, 2021 22 95 3.96 Fri Jan 22, 2021 21 71 2.96 Tue Jan 26, 2021 08 103 4.29 Sun Jan 31, 2021 23 115 4.79 Fri Feb 05, 2021 01 118 4.92 Mon Feb 08, 2021 20 71 2.96 Thu Feb 11, 2021 18 80 3.33 Tue Feb 16, 2021 08 120 5.00 Fri Feb 19, 2021 18 72 3.00 Wed Feb 24, 2021 01 113 4.71 Sun Feb 28, 2021 22 97 4.04 Thu Mar 04, 2021 11 95 3.96 Mon Mar 08, 2021 18 103 4.29 Sat Mar 13, 2021 15 117 4.88 Wed Mar 17, 2021 10 91 3.79 Sun Mar 21, 2021 00 96 4.00 Fri Mar 26, 2021 00 120 5.00 Tue Mar 30, 2021 17 103 4.29 Sat Apr 03, 2021 00 89 3.71 Wed Apr 07, 2021 23 99 4.12 Sun Apr 11, 2021 05 98 4.08 Thu Apr 15, 2021 14 95 3.96 Sun Apr 18, 2021 23 71 2.96 Fri Apr 23, 2021 23 120 5.00 Tue Apr 27, 2021 17 100 4.17 Tue Jul 27, 2021 21 2178 90.75 Sun Aug 01, 2021 18 127 5.29 Thu Aug 05, 2021 23 91 3.79 Tue Aug 10, 2021 17 124 5.17 Sat Aug 14, 2021 21 90 3.75 Thu Aug 19, 2021 09 128 5.33 Wed Aug 25, 2021 02 137 5.71 -----Original Message----- From: Python-list On Behalf Of David Lowry-Duda Sent: Friday, August 27, 2021 3:25 PM To: python-list at python.org Subject: Re: matplotlib questions > I am trying to modify the "Bar Graph Demo" at > https://matplotlib.org/stable/gallery/index.html, Lines, bars, and > markers but the more I experiment and change the code, the more messed > up it becomes. It is much easier to give constructive suggestions if you give a minimum runnable code sample that indicates what you're trying and what you're trying to do. See also http://catb.org/~esr/faqs/smart-questions.html I'll also note that I see nothing called "bar graph demo" on the gallery page. - DLD -- https://mail.python.org/mailman/listinfo/python-list From hrouselle at jevedi.com Sat Aug 28 06:37:58 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Sat, 28 Aug 2021 07:37:58 -0300 Subject: on perhaps unloading modules? References: <867dgfinp6.fsf@jevedi.com> <86a6lahoml.fsf@jevedi.com> <868s0uftbh.fsf@jevedi.com> <7st4ig986242i36gqemgr5e1kub6s8t6ld@4ax.com> <86o89p9t4j.fsf@jevedi.com> <20210824220249.GA5110@hjp.at> Message-ID: <867dg5n9bt.fsf@jevedi.com> "Peter J. Holzer" writes: > On 2021-08-22 16:28:12 -0300, Hope Rouselle wrote: >> I have a certain distaste for syntax too. For instance, I would much >> rather write and read ``first(ls)'' than ``ls[0]''. > > Would you also prefer `twothousandthreehundredandtwentythird(ls)` over > `ls[2322]`? Omg, I'm afraid you are serious! :-D We could use something like list_get(ls, 2322). Of course that ls[2322] is perfect fine. From hrouselle at jevedi.com Sat Aug 28 08:00:27 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Sat, 28 Aug 2021 09:00:27 -0300 Subject: on writing a while loop for rolling two dice Message-ID: <86r1edlqxw.fsf@jevedi.com> How should I write this? I'd like to roll two six-sided dice until I get the same number on both. I'd like to get the number of times I tried. Here's a primitive I'm using: --8<---------------cut here---------------start------------->8--- >>> x, y = roll() >>> x 6 >>> y 6 # lucky >>> x, y = roll() >>> x 4 >>> y 1 # unlucky --8<---------------cut here---------------end--------------->8--- Here's my solution: --8<---------------cut here---------------start------------->8--- def how_many_times(): x, y = 0, 1 c = 0 while x != y: c = c + 1 x, y = roll() return c, (x, y) --8<---------------cut here---------------end--------------->8--- Why am I unhappy? I'm wish I could confine x, y to the while loop. The introduction of ``x, y = 0, 1'' must feel like a trick to a novice. How would you write this? Thank you! From hrouselle at jevedi.com Sat Aug 28 09:31:55 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Sat, 28 Aug 2021 10:31:55 -0300 Subject: on the popularity of loops while and for Message-ID: <86eeadlmpg.fsf@jevedi.com> I'd like get a statistic of how often each loop is used in practice. I was trying to take a look at the Python's standard libraries --- those included in a standard installation of Python 3.9.6, say --- to see which loops are more often used among while and for loops. Of course, since English use the preposition ``for'' a lot, that makes my life harder. Removing comments is easy, but removing strings is harder. So I don't know yet what I'll do. Have you guys ever measured something like that in a casual or serious way? I'd love to know. Thank you! From hrouselle at jevedi.com Sat Aug 28 16:46:52 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Sat, 28 Aug 2021 17:46:52 -0300 Subject: on writing a while loop for rolling two dice References: <86r1edlqxw.fsf@jevedi.com> Message-ID: <86a6l1thz7.fsf@jevedi.com> ram at zedat.fu-berlin.de (Stefan Ram) writes: > Hope Rouselle writes: >>How would you write this? > > """Rolls two dice until both yield the same value. > Returns the number of times the two dice were rolled > and the final value yielded.""" > roll_count = 0 > while True: > outcome = roll_two_dice() > roll_count += 1 > if outcome[ 0 ]== outcome[ 1 ]: break > return roll_count, outcome[ 0 ] You totally convinced me. Thanks. From hrouselle at jevedi.com Sat Aug 28 16:50:01 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Sat, 28 Aug 2021 17:50:01 -0300 Subject: on writing a while loop for rolling two dice References: <86r1edlqxw.fsf@jevedi.com> <86a6l1thz7.fsf@jevedi.com> Message-ID: <861r6dthty.fsf@jevedi.com> Hope Rouselle writes: > ram at zedat.fu-berlin.de (Stefan Ram) writes: > >> Hope Rouselle writes: >>>How would you write this? >> >> """Rolls two dice until both yield the same value. >> Returns the number of times the two dice were rolled >> and the final value yielded.""" >> roll_count = 0 >> while True: >> outcome = roll_two_dice() >> roll_count += 1 >> if outcome[ 0 ]== outcome[ 1 ]: break >> return roll_count, outcome[ 0 ] > > You totally convinced me. Thanks. Wait, I'm surprised ``outcome'' is still a valid name at the return-statement. Wasn't it defined inside the while? Shouldn't its scope be restricted to the while block? I had no idea. I should learn some Python. From hrouselle at jevedi.com Sat Aug 28 17:15:02 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Sat, 28 Aug 2021 18:15:02 -0300 Subject: on the popularity of loops while and for References: <86eeadlmpg.fsf@jevedi.com> Message-ID: <86sfyts23t.fsf@jevedi.com> ram at zedat.fu-berlin.de (Stefan Ram) writes: > Hope Rouselle writes: >>Have you guys ever measured something like that in a casual or serious > > import ast > import pathlib > rootname=r'''''' > rootpath=pathlib.Path(rootname) > rootiterable=rootpath.glob('**/*.py') > first = True > WhileCount = 0 > ForCount = 0 > for filepath in rootiterable: > try: > with filepath.open(encoding="utf-8") as file: > source=file.read() > parse=ast.parse(source, filename=str(file)) > for entry in ast.walk(parse): > if isinstance(entry, ast.While): > WhileCount+=1 > print( f"{ForCount=}, {WhileCount=}" ) > elif isinstance(entry, ast.For): > ForCount+=1 > print( f"{ForCount=}, {WhileCount=}" ) > except SyntaxError as inst: > if first: > print( f"{sys.exc_info()[ 0 ] =}" ) > print( f"{type( inst ) =}" ) > print( f"{inst.args =}" ) > print( f"{inst =}" ) > print( f"skipping {filepath}." ) > first=False You are so wonderful! Thanks quite a lot. Here's what I got: ForCount=18703, WhileCount=2505 I have pretty much just the standard libraries and a couple more --- sympy and some xlsxwriter library. From hrouselle at jevedi.com Sat Aug 28 17:17:26 2021 From: hrouselle at jevedi.com (Hope Rouselle) Date: Sat, 28 Aug 2021 18:17:26 -0300 Subject: on writing a while loop for rolling two dice References: <86r1edlqxw.fsf@jevedi.com> <86a6l1thz7.fsf@jevedi.com> <861r6dthty.fsf@jevedi.com> Message-ID: <86k0k5s1zt.fsf@jevedi.com> ram at zedat.fu-berlin.de (Stefan Ram) writes: > Hope Rouselle writes: >>Wait, I'm surprised ``outcome'' is still a valid name at the >>return-statement. Wasn't it defined inside the while? Shouldn't its >>scope be restricted to the while block? I had no idea. I should learn >>some Python. > > In Python, local names can be introduced by an assignment > and have function scope. There is no block scope in Python. > > Below, "name" /is/ a local name already, but is being > used before being assigned to. > > def function(): > if False: > name = 0 > return name > > function() > > # return name > # UnboundLocalError: local variable 'name' referenced before assignment I appreciated the example. I had no idea. (I had looked up the rules and it was pretty simple to understand, but an example is always nice.) Thank you so much. From mehrzad.1024 at gmail.com Sat Aug 28 10:31:38 2021 From: mehrzad.1024 at gmail.com (Mehrzad Saremi) Date: Sat, 28 Aug 2021 19:01:38 +0430 Subject: PEP Idea: Real private attribute Message-ID: Python currently uses name mangling for double-underscore attributes. Name mangling is not an ideal method to avoid name conflicting. There are various normal programming patterns that can simply cause name conflicting in double-underscore members. A typical example is when a class is re-decorated using the same decorator. The decorator can not take double-underscore members without name conflicts. For example: ``` @custom_decorator("a") @custom_decorator("b") class C: pass ``` The `@custom_decorator` wrapper may need to hold private members, but Python's current name conflict resolution does not provide any solution and the decorator cannot hold private members without applying tricky programming methods. Another example is when a class inherits from a base class of the same name. ``` class View: """A class representing a view of an object; similar to numpy.ndarray.view""" pass class Object: class View(View): """A view class costumized for objects of type Object""" pass ``` Again, in this example, class `Object.View` can't take double-underscore names without conflicting with `View`'s. My idea is to introduce real private members (by which I do not mean to be inaccessible from outside the class, but to be guaranteed not to conflict with other private members of the same object). These private members are started with triple underscores and are stored in a separate dictionary named `__privs__`. Unlike `__dict__` that takes 'str' keys, `__privs__` will be a double layer dictionary that takes 'type' keys in the first level, and 'str' keys in the second level. For example, assume that the user runs the following code: ``` class C: def __init__(self, value): self.___member = value c = C("my value") ``` On the last line, Python's attribute setter creates a new entry in the dictionary with key `C`, adds the value "my value" to a new entry with the key 'member'. The user can then retrieve `c.___member` by invoking the `__privs__` dictionary: ``` print(c.__privs__[C]['member']) # prints 'my value' ``` Note that, unlike class names, class objects are unique and there will not be any conflicts. Python classes are hashable and can be dictionary keys. Personally, I do not see any disadvantage of using __privs__ over name mangling/double-underscores. While name mangling does not truly guarantee conflict resolution, __privs__ does. Please discuss the idea, let me know what you think about it, whether there are possible disadvantages, and if you think it will be approved as a PEP. Thanks, Mehrzad Saremi AI M.Sc. grad. from AUT From rosuav at gmail.com Sat Aug 28 17:41:21 2021 From: rosuav at gmail.com (Chris Angelico) Date: Sun, 29 Aug 2021 07:41:21 +1000 Subject: on writing a while loop for rolling two dice In-Reply-To: <86r1edlqxw.fsf@jevedi.com> References: <86r1edlqxw.fsf@jevedi.com> Message-ID: On Sun, Aug 29, 2021 at 7:37 AM Hope Rouselle wrote: > > How should I write this? I'd like to roll two six-sided dice until I > get the same number on both. I'd like to get the number of times I > tried. Here's a primitive I'm using: > > --8<---------------cut here---------------start------------->8--- > >>> x, y = roll() > >>> x > 6 > >>> y > 6 # lucky > > >>> x, y = roll() > >>> x > 4 > >>> y > 1 # unlucky > --8<---------------cut here---------------end--------------->8--- > > Here's my solution: > > --8<---------------cut here---------------start------------->8--- > def how_many_times(): > x, y = 0, 1 > c = 0 > while x != y: > c = c + 1 > x, y = roll() > return c, (x, y) > --8<---------------cut here---------------end--------------->8--- > > Why am I unhappy? I'm wish I could confine x, y to the while loop. The > introduction of ``x, y = 0, 1'' must feel like a trick to a novice. How > would you write this? Thank you! Your loop, fundamentally, is just counting. So let's just count. def how_many_times(): for c in itertools.count(): ... Inside that loop, you can do whatever you like, including returning immediately if you have what you want. I'll let you figure out the details. :) ChrisA From rosuav at gmail.com Sat Aug 28 17:43:35 2021 From: rosuav at gmail.com (Chris Angelico) Date: Sun, 29 Aug 2021 07:43:35 +1000 Subject: on the popularity of loops while and for In-Reply-To: <86eeadlmpg.fsf@jevedi.com> References: <86eeadlmpg.fsf@jevedi.com> Message-ID: On Sun, Aug 29, 2021 at 7:40 AM Hope Rouselle wrote: > > I'd like get a statistic of how often each loop is used in practice. > > I was trying to take a look at the Python's standard libraries --- those > included in a standard installation of Python 3.9.6, say --- to see > which loops are more often used among while and for loops. Of course, > since English use the preposition ``for'' a lot, that makes my life > harder. Removing comments is easy, but removing strings is harder. So > I don't know yet what I'll do. > > Have you guys ever measured something like that in a casual or serious > way? I'd love to know. Thank you! For analysis like this, I recommend using the Abstract Syntax Tree: https://docs.python.org/3/library/ast.html You can take a Python source file, parse it to the AST, and then walk that tree to see what it's using. That will avoid any false positives from the word "for" coming up in the wrong places. ChrisA From rosuav at gmail.com Sat Aug 28 17:48:22 2021 From: rosuav at gmail.com (Chris Angelico) Date: Sun, 29 Aug 2021 07:48:22 +1000 Subject: PEP Idea: Real private attribute In-Reply-To: References: Message-ID: On Sun, Aug 29, 2021 at 7:40 AM Mehrzad Saremi wrote: > > Python currently uses name mangling for double-underscore attributes. Name > mangling is not an ideal method to avoid name conflicting. There are > various normal programming patterns that can simply cause name conflicting > in double-underscore members. A typical example is when a class is > re-decorated using the same decorator. The decorator can not take > double-underscore members without name conflicts. For example: > > ``` > @custom_decorator("a") > @custom_decorator("b") > class C: > pass > ``` > > The `@custom_decorator` wrapper may need to hold private members, but > Python's current name conflict resolution does not provide any solution and > the decorator cannot hold private members without applying tricky > programming methods. > > Another example is when a class inherits from a base class of the same name. > > ``` > class View: > """A class representing a view of an object; similar to > numpy.ndarray.view""" > pass > > class Object: > class View(View): > """A view class costumized for objects of type Object""" > pass > ``` > > Again, in this example, class `Object.View` can't take double-underscore > names without conflicting with `View`'s. > > My idea is to introduce real private members (by which I do not mean to be > inaccessible from outside the class, but to be guaranteed not to conflict > with other private members of the same object). These private members are > started with triple underscores and are stored in a separate dictionary > named `__privs__`. Unlike `__dict__` that takes 'str' keys, `__privs__` > will be a double layer dictionary that takes 'type' keys in the first > level, and 'str' keys in the second level. > > For example, assume that the user runs the following code: > ``` > class C: > def __init__(self, value): > self.___member = value > > c = C("my value") > ``` > > On the last line, Python's attribute setter creates a new entry in the > dictionary with key `C`, adds the value "my value" to a new entry with the > key 'member'. > > The user can then retrieve `c.___member` by invoking the `__privs__` > dictionary: > > ``` > print(c.__privs__[C]['member']) # prints 'my value' > ``` > > Note that, unlike class names, class objects are unique and there will not > be any conflicts. Python classes are hashable and can be dictionary keys. > Personally, I do not see any disadvantage of using __privs__ over name > mangling/double-underscores. While name mangling does not truly guarantee > conflict resolution, __privs__ does. Not entirely sure how it would know the right type to use (subclassing makes that tricky), but whatever your definition is, there's nothing stopping you from doing it yourself. Don't forget that you have __class__ available if you need to refer to "the class that I'm lexically inside" (that's how the zero-arg super() function works), so you might do something like self.__privs__[__class__, "foo"] to refer to a thing. ChrisA From stestagg at gmail.com Sat Aug 28 18:05:12 2021 From: stestagg at gmail.com (Stestagg) Date: Sat, 28 Aug 2021 23:05:12 +0100 Subject: on the popularity of loops while and for In-Reply-To: <86sfyts23t.fsf@jevedi.com> References: <86eeadlmpg.fsf@jevedi.com> <86sfyts23t.fsf@jevedi.com> Message-ID: If you're doing this analysis, I'd be pretty interested in how many of those while loops where 'while True:' I'd wager 75%. But may be completely off Steve On Sat, 28 Aug 2021 at 23:03, Hope Rouselle wrote: > ram at zedat.fu-berlin.de (Stefan Ram) writes: > > > Hope Rouselle writes: > >>Have you guys ever measured something like that in a casual or serious > > > > import ast > > import pathlib > > rootname=r'''''' > > rootpath=pathlib.Path(rootname) > > rootiterable=rootpath.glob('**/*.py') > > first = True > > WhileCount = 0 > > ForCount = 0 > > for filepath in rootiterable: > > try: > > with filepath.open(encoding="utf-8") as file: > > source=file.read() > > parse=ast.parse(source, filename=str(file)) > > for entry in ast.walk(parse): > > if isinstance(entry, ast.While): > > WhileCount+=1 > > print( f"{ForCount=}, {WhileCount=}" ) > > elif isinstance(entry, ast.For): > > ForCount+=1 > > print( f"{ForCount=}, {WhileCount=}" ) > > except SyntaxError as inst: > > if first: > > print( f"{sys.exc_info()[ 0 ] =}" ) > > print( f"{type( inst ) =}" ) > > print( f"{inst.args =}" ) > > print( f"{inst =}" ) > > print( f"skipping {filepath}." ) > > first=False > > You are so wonderful! Thanks quite a lot. Here's what I got: > > ForCount=18703, WhileCount=2505 > > I have pretty much just the standard libraries and a couple more --- > sympy and some xlsxwriter library. > -- > https://mail.python.org/mailman/listinfo/python-list > From PythonList at DancesWithMice.info Sat Aug 28 18:42:28 2021 From: PythonList at DancesWithMice.info (dn) Date: Sun, 29 Aug 2021 10:42:28 +1200 Subject: on writing a while loop for rolling two dice In-Reply-To: <86a6l1thz7.fsf@jevedi.com> References: <86r1edlqxw.fsf@jevedi.com> <86a6l1thz7.fsf@jevedi.com> Message-ID: <4b8ed591-2f2f-6c76-4606-b431f52cf847@DancesWithMice.info> On 29/08/2021 08.46, Hope Rouselle wrote: > Here's my solution: > > --8<---------------cut here---------------start------------->8--- > def how_many_times(): > x, y = 0, 1 > c = 0 > while x != y: > c = c + 1 > x, y = roll() > return c, (x, y) > > Why am I unhappy? I'm wish I could confine x, y to the while loop. The > introduction of ``x, y = 0, 1'' must feel like a trick to a novice. How > would you write this? > ram at zedat.fu-berlin.de (Stefan Ram) writes: >> """Rolls two dice until both yield the same value. >> Returns the number of times the two dice were rolled >> and the final value yielded.""" >> roll_count = 0 >> while True: >> outcome = roll_two_dice() >> roll_count += 1 >> if outcome[ 0 ]== outcome[ 1 ]: break >> return roll_count, outcome[ 0 ] > > You totally convinced me. Thanks. On the other hand... whilst you expressed concern about the apparently disconnected 'set up' necessary before the loop, this solution adds a "True/Forever" and a "Break" construct, which some may deem not that much better (if at all) The idea of abrogating the while-condition but then adding another (disconnected) condition to break, seems to hold equal potential for confusion. or the type of dissatisfaction which motivated the original question! Looking at that from the inside-out, the loop's contents perform two functions: the rolling and counting (per Statement of Requirements), but also a loop-controlling element. Thus the reader's question: "what does this loop do?" is conflated with "how many times does it do it?". Let's go completely off-the-rails, why not use a never-ending range() to fuel a for-loop 'counter', and within that loop perform the dice-roll(s) and decide if it is time to 'break'. The range replaces the "True". The for-loops index or 'counter' will deliver the desired result. Neat? No! Readable? No! An improvement over the while-True? Definitely not! Yet, the mechanism is the same AND offers a built-in counter. Hmmm... Returning to the concern: x, y = 0, 1 c = 0 The first line is purely to ensure that the loop executes at least once, ie the two assigned-values are not 'real'. Hence the disquiet! Initiating the counter is unavoidable (@Chris' suggestion notwithstanding). However, remember that Python (like decent DBs) has a concept (and an idiom) of a value to be used when we don't (yet) know what the value is/should be! Further that Python allows such a value to be used in comparisons: >>> None != None False >>> None == None True Leading to: c, x, y = 0, None, None while ... Which solution reverts to the original loop-contents. which seem more obvious and thus more readable. (YMMV!) Simplicity over 'being clever'... -- Regards, =dn From tjreedy at udel.edu Sat Aug 28 17:54:07 2021 From: tjreedy at udel.edu (Terry Reedy) Date: Sat, 28 Aug 2021 17:54:07 -0400 Subject: on the popularity of loops while and for In-Reply-To: <86eeadlmpg.fsf@jevedi.com> References: <86eeadlmpg.fsf@jevedi.com> Message-ID: On 8/28/2021 9:31 AM, Hope Rouselle wrote: > I'd like get a statistic of how often each loop is used in practice. My guess is that for loops are at least twice as common as while loops. > I was trying to take a look at the Python's standard libraries --- those > included in a standard installation of Python 3.9.6, say --- to see > which loops are more often used among while and for loops. Of course, > since English use the preposition ``for'' a lot, that makes my life > harder. Removing comments is easy, but removing strings is harder. So > I don't know yet what I'll do. Try something like fors = 0 for file in files: for line in file: if re.match(r"/s*for .* in ", line): fors += 1 This excludes comprehensions, which have replaced some for loops. -- Terry Jan Reedy From tjreedy at udel.edu Sat Aug 28 18:00:49 2021 From: tjreedy at udel.edu (Terry Reedy) Date: Sat, 28 Aug 2021 18:00:49 -0400 Subject: on writing a while loop for rolling two dice In-Reply-To: <86r1edlqxw.fsf@jevedi.com> References: <86r1edlqxw.fsf@jevedi.com> Message-ID: On 8/28/2021 8:00 AM, Hope Rouselle wrote: > How should I write this? I'd like to roll two six-sided dice until I > get the same number on both. I'd like to get the number of times I > tried. Here's a primitive I'm using: > > --8<---------------cut here---------------start------------->8--- >>>> x, y = roll() >>>> x > 6 >>>> y > 6 # lucky > >>>> x, y = roll() >>>> x > 4 >>>> y > 1 # unlucky > --8<---------------cut here---------------end--------------->8--- > > Here's my solution: > > --8<---------------cut here---------------start------------->8--- > def how_many_times(): > x, y = 0, 1 > c = 0 > while x != y: > c = c + 1 > x, y = roll() > return c, (x, y) > --8<---------------cut here---------------end--------------->8--- > > Why am I unhappy? I'm wish I could confine x, y to the while loop. The > introduction of ``x, y = 0, 1'' must feel like a trick to a novice. How > would you write this? Thank you! Something like (untested) c = 0 while True: c += 1 x, y = roll() if x == y: return c, (x,y) or even better to me, as it will not loop forever if you mess up the condition for i in range(1, 1000000): x, y = roll() if x == y: return i, (x,y) # return "The universe ends as the essentially impossible happened" -- Terry Jan Reedy From alan.gauld at yahoo.co.uk Sat Aug 28 18:51:44 2021 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Sat, 28 Aug 2021 23:51:44 +0100 Subject: on writing a while loop for rolling two dice In-Reply-To: <861r6dthty.fsf@jevedi.com> References: <86r1edlqxw.fsf@jevedi.com> <86a6l1thz7.fsf@jevedi.com> <861r6dthty.fsf@jevedi.com> Message-ID: On 28/08/2021 21:50, Hope Rouselle wrote: >>> roll_count = 0 >>> while True: >>> outcome = roll_two_dice() >>> roll_count += 1 >>> if outcome[ 0 ]== outcome[ 1 ]: break >>> return roll_count, outcome[ 0 ] >> > > Wait, I'm surprised ``outcome'' is still a valid name at the > return-statement. Wasn't it defined inside the while? If that really bugs you just replace the break with the return. >>> if outcome[ 0 ]== outcome[ 1 ]: >>> return roll_count, outcome[ 0 ] Now its all inside the loop. But remember readable code is better than cute code every time. And personally I'd just declare the x,y up front. Easier to understand and debug IMHO. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From stestagg at gmail.com Sat Aug 28 19:09:45 2021 From: stestagg at gmail.com (Stestagg) Date: Sun, 29 Aug 2021 00:09:45 +0100 Subject: on the popularity of loops while and for In-Reply-To: References: <86eeadlmpg.fsf@jevedi.com> <86sfyts23t.fsf@jevedi.com> Message-ID: On Sun, 29 Aug 2021 at 00:04, Stefan Ram wrote: > Stestagg writes: > >If you're doing this analysis, I'd be pretty interested in how many of > >those while loops where 'while True:' > > Here, about 40 %. Thanks! That's an interesting stat. I might have to look more into how while loops are actually used in other people's code. > > Below is a new version that is supposed to also count "if True:" > and "if 1:" and also removes a bug with the exception handling > (missing "import sys" and missing "UnicodeDecodeError"). I'm not > experienced in using the AST module, so there might still be bugs > in the program! > > import ast > import pathlib > import sys > rootname=r'''PATH TO SOURCE DIR (WITHOUT A BACKQUOTE AT THE END)''' > rootpath=pathlib.Path(rootname) > rootiterable=rootpath.glob('**/*.py') > WhileCount = 0 > TrueCount = 0 > ForCount = 0 > for filepath in rootiterable: > try: > with filepath.open(encoding="utf-8") as file: > source=file.read() > parse=ast.parse(source, filename=str(file)) > for entry in ast.walk(parse): > if isinstance(entry, ast.While): > WhileCount+=1 > if ( isinstance( entry.test, ast.Constant ) and > hasattr( entry.test, "value") and > ( isinstance( entry.test.value, bool ) > and entry.test.value == True or > isinstance( entry.test.value, int ) > and entry.test.value != 0 )): > TrueCount+=1 > print( f"{ForCount=}, {WhileCount=}, {TrueCount=}" ) > elif isinstance(entry, ast.For): > ForCount+=1 > print( f"{ForCount=}, {WhileCount=}" ) > except ( SyntaxError, UnicodeDecodeError )as inst: > print( f"skipping {filepath}." ) > print( f"{sys.exc_info()[ 0 ] =}" ) > print( f"{type( inst ) =}" ) > print( f"{inst.args =}" ) > print( f"{inst =}\n" ) > print( f"{ForCount=}, {WhileCount=}, {TrueCount=}" ) > > > -- > https://mail.python.org/mailman/listinfo/python-list > From python at mrabarnett.plus.com Sat Aug 28 19:17:45 2021 From: python at mrabarnett.plus.com (MRAB) Date: Sun, 29 Aug 2021 00:17:45 +0100 Subject: matplotlib questions In-Reply-To: <005c01d79bbe$410754d0$c315fe70$@SGA.Ninja> References: <000801d79a91$b4d851d0$1e88f570$@SGA.Ninja> <005c01d79bbe$410754d0$c315fe70$@SGA.Ninja> Message-ID: <65c7af17-9982-fb85-f143-b8559759dda0@mrabarnett.plus.com> On 2021-08-28 04:39, Steve wrote: > I would like to know how the data is placed on the Y-axis and at the tops of > the bars. > The data is not being shown properly. With some exceptions, it looks as if > the data is getting sorted independently from the dates. > > > OK, here is the code: > ============================================== > # https://matplotlib.org/stable/gallery/index.html > import matplotlib.pyplot as plt > import numpy as np > > width = 12 #Width of the graph > height = 6 #Height of the graph > > plt.rcParams["figure.figsize"] = (width,height) > plt.rcParams["font.size"] = (9.0) > > > Count = 0 > datesList = [] # Each date showing end of bottle use > hoursList = [] # Number of hours > # daysList = [] # Number of days calculated from hours/24 > countList = [] # simple tally > > with open("__Insulin_Tracker.txt", 'r') as infile: > for lineEQN in infile: > insulinHours = lineEQN[47:52].strip() > print("Hours = " + insulinHours) > hoursList.append(insulinHours) > > insulinDates = lineEQN[20:30].strip() > datesList.append(insulinDates) > > # insulinDays= lineEQN[57:62].strip() > # daysList.append(insulinDays) > > Count += 1 > countList.append(str(Count)) > # print(" " + str(Count) + " " + insulinDates + " Hours: " + > insulinHours) > x = Count > count = str(Count) > > # Each date indicated the date on which a bottle of insulin has been > depleted > # The bar is to show the number of hours that the bottle has been in use. > > Labels = datesList > Xdata= hoursList > > Title = ("Bottle List Number of entries: " + count) > x = np.arange(len(Labels)) # the label locations > > width = 0.35 # the width of the bars > margin = 0 > > fig, ax = plt.subplots() > fig.tight_layout(pad=10) # Sets the size of the graph > > rects1 = ax.bar(x - width/2, Xdata, width, label='Hours') #Populates the x > axis > > # Add some text for labels, title and custom x-axis tick labels, etc. > # fontsize = 20 > > ax.set_ylabel('Hours of use for each bottle') > ax.set_title(Title) > ax.set_xticks(x) > ax.set_xticklabels((datesList), rotation = 90) #Dates at bottom of the graph > ax.legend() > ax.bar_label(rects1, padding=0,rotation = 90) > > plt.show() > [snip] You're passing ax.bar the contents of Xdata. What does Xdata contain? A list of _strings_. If you want the length of the bars to represent the number of hours, then they should be numbers. From avigross at verizon.net Sat Aug 28 20:19:02 2021 From: avigross at verizon.net (Avi Gross) Date: Sat, 28 Aug 2021 20:19:02 -0400 Subject: on writing a while loop for rolling two dice In-Reply-To: References: <86r1edlqxw.fsf@jevedi.com> <86a6l1thz7.fsf@jevedi.com> <861r6dthty.fsf@jevedi.com> Message-ID: <012701d79c6b$786074e0$69215ea0$@verizon.net> And there is the ever popular recursive version you call with no while loop in sight. And, oddly, no variable declared in your main body: #---- CODE START --- import random def roll2(): return random.randint(1,6), random.randint(1,6) def roll_equal(counter): first, second = roll2() encountered = counter + 1 if (first == second): return(encountered) else: return(roll_equal(encountered)) #--- CODE END --- Since the result is usually a single digit of iterations, no biggie. Here is some output: >>> roll_equal(0) 6 >>> roll_equal(0) 7 >>> roll_equal(0) 1 >>> roll_equal(0) 7 >>> roll_equal(0) 6 >>> [ roll_equal(0) for n in range(10)] [3, 4, 2, 5, 8, 1, 1, 2, 3, 9] >>> [ roll_equal(0) for n in range(10)] [3, 3, 7, 19, 7, 2, 1, 3, 8, 4] >>> [ roll_equal(0) for n in range(10)] [1, 3, 1, 13, 11, 4, 3, 5, 2, 4] And the code can be a tad shorter, LOL! But obviously then you have more overhead than an iterative solution or one using a generator ... -----Original Message----- From: Python-list On Behalf Of Alan Gauld via Python-list Sent: Saturday, August 28, 2021 6:52 PM To: python-list at python.org Subject: Re: on writing a while loop for rolling two dice On 28/08/2021 21:50, Hope Rouselle wrote: >>> roll_count = 0 >>> while True: >>> outcome = roll_two_dice() >>> roll_count += 1 >>> if outcome[ 0 ]== outcome[ 1 ]: break return roll_count, >>> outcome[ 0 ] >> > > Wait, I'm surprised ``outcome'' is still a valid name at the > return-statement. Wasn't it defined inside the while? If that really bugs you just replace the break with the return. >>> if outcome[ 0 ]== outcome[ 1 ]: >>> return roll_count, outcome[ 0 ] Now its all inside the loop. But remember readable code is better than cute code every time. And personally I'd just declare the x,y up front. Easier to understand and debug IMHO. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos -- https://mail.python.org/mailman/listinfo/python-list From __peter__ at web.de Sun Aug 29 04:06:47 2021 From: __peter__ at web.de (Peter Otten) Date: Sun, 29 Aug 2021 10:06:47 +0200 Subject: on writing a while loop for rolling two dice In-Reply-To: <86r1edlqxw.fsf@jevedi.com> References: <86r1edlqxw.fsf@jevedi.com> Message-ID: On 28/08/2021 14:00, Hope Rouselle wrote: > def how_many_times(): > x, y = 0, 1 > c = 0 > while x != y: > c = c + 1 > x, y = roll() > return c, (x, y) > --8<---------------cut here---------------end--------------->8--- > > Why am I unhappy? I'm wish I could confine x, y to the while loop. The > introduction of ``x, y = 0, 1'' must feel like a trick to a novice. How > would you write this? Thank you! I'd probably hide the while loop under the rug: >>> import random >>> def roll_die(): while True: yield random.randrange(1, 7) Then: >>> def hmt(): for c, (x, y) in enumerate(zip(roll_die(), roll_die()), 1): if x == y: return c, (x, y) >>> hmt() (1, (2, 2)) >>> hmt() (4, (4, 4)) >>> hmt() (1, (5, 5)) OK, maybe a bit complicated... but does it pay off if you want to generalize? >>> def roll_die(faces): while True: yield random.randrange(1, 1 + faces) >>> def hmt(faces, dies): for c, d in enumerate(zip(*[roll_die(faces)]*dies), 1): if len(set(d)) == 1: return c, d >>> hmt(10, 1) (1, (2,)) >>> hmt(10, 2) (3, (10, 10)) >>> hmt(10, 3) (250, (5, 5, 5)) >>> hmt(1, 10) (1, (1, 1, 1, 1, 1, 1, 1, 1, 1, 1)) You decide :) From barry at barrys-emacs.org Sun Aug 29 05:04:47 2021 From: barry at barrys-emacs.org (Barry) Date: Sun, 29 Aug 2021 10:04:47 +0100 Subject: on the popularity of loops while and for Message-ID: ? > On 28 Aug 2021, at 22:42, Hope Rouselle wrote: > > ?I'd like get a statistic of how often each loop is used in practice. > > I was trying to take a look at the Python's standard libraries --- those > included in a standard installation of Python 3.9.6, say --- to see > which loops are more often used among while and for loops. Of course, > since English use the preposition ``for'' a lot, that makes my life > harder. Removing comments is easy, but removing strings is harder. So > I don't know yet what I'll do. > > Have you guys ever measured something like that in a casual or serious > way? I'd love to know. Thank you! I am interesting in why you think that choice of while vs. for is about popularity? Surely the choice is made in most cases by the algorithm? If you have an iterator then you use for. Of course you can use while instead of for but in code review that will get queried. Barry > -- > https://mail.python.org/mailman/listinfo/python-list From PythonList at DancesWithMice.info Sun Aug 29 06:13:03 2021 From: PythonList at DancesWithMice.info (dn) Date: Sun, 29 Aug 2021 22:13:03 +1200 Subject: on writing a while loop for rolling two dice In-Reply-To: References: <86r1edlqxw.fsf@jevedi.com> Message-ID: On 29/08/2021 20.06, Peter Otten wrote: ... > OK, maybe a bit complicated... but does it pay off if you want to > generalize? > >>>> def roll_die(faces): > ????while True: yield random.randrange(1, 1 + faces) > >>>> def hmt(faces, dies): > ????for c, d in enumerate(zip(*[roll_die(faces)]*dies), 1): > ??????? if len(set(d)) == 1: return c, d Curiosity: why not add dies as a parameter of roll_die()? Efficiency: - wonder how max( d ) == min( d ) compares for speed with the set() type constructor? - alternately len( d ) < 2? - or len( d ) - 1 coerced to a boolean by the if? - how much more efficient is any of this (clever thinking!) than the OP's basic, simpler, and thus more readable, form? English language 'treachery': - one die - multiple dice (probably not followed in US-English (can't recall), particularly on computers running the Hollywood Operating System). Continuous Education: Thanks for the reminder that enumerate() can be seeded with a "start" value! -- Regards, =dn From rosuav at gmail.com Sun Aug 29 06:24:23 2021 From: rosuav at gmail.com (Chris Angelico) Date: Sun, 29 Aug 2021 20:24:23 +1000 Subject: on writing a while loop for rolling two dice In-Reply-To: References: <86r1edlqxw.fsf@jevedi.com> Message-ID: On Sun, Aug 29, 2021 at 8:14 PM dn via Python-list wrote: > Efficiency: > - wonder how max( d ) == min( d ) compares for speed with the set() type > constructor? That may or may not be an improvement. > - alternately len( d ) < 2? > - or len( d ) - 1 coerced to a boolean by the if? Neither of these will make any notable improvement. The work is done in constructing the set, and then you're taking the length. How you do the comparison afterwards is irrelevant. ChrisA From __peter__ at web.de Sun Aug 29 08:47:50 2021 From: __peter__ at web.de (Peter Otten) Date: Sun, 29 Aug 2021 14:47:50 +0200 Subject: on writing a while loop for rolling two dice In-Reply-To: References: <86r1edlqxw.fsf@jevedi.com> Message-ID: On 29/08/2021 12:13, dn via Python-list wrote: > On 29/08/2021 20.06, Peter Otten wrote: > ... >> OK, maybe a bit complicated... but does it pay off if you want to >> generalize? >> >>>>> def roll_die(faces): >> ????while True: yield random.randrange(1, 1 + faces) >> >>>>> def hmt(faces, dies): >> ????for c, d in enumerate(zip(*[roll_die(faces)]*dies), 1): >> ??????? if len(set(d)) == 1: return c, d > > > Curiosity: > why not add dies as a parameter of roll_die()? Dunno. Maybe because I've "always" [1] wanted a version of random.randrange() that generates values indefinitely. It would need to check its arguments only once, thus leading to some extra > Efficiency: > - wonder how max( d ) == min( d ) compares for speed with the set() type > constructor? I did the simplest thing, speed was not a consideration. If it is, and dies (sorry for that) is large I'd try first = d[0] all(x == first for x in d) # don't mind one duplicate test For smaller numbers of dice I'd unpack (first, *rest) inside the for loop. But it's a trade-off, you' have to measure if/when it's better to go through the whole tuple in C. > - alternately len( d ) < 2? > - or len( d ) - 1 coerced to a boolean by the if? > - how much more efficient is any of this (clever thinking!) than the > OP's basic, simpler, and thus more readable, form? It really isn't efficiency, it's a (misled?) sense of aesthetics where I've come to prefer - for-loops over while, even when I end up with both to get the desired for - enumerate() over an explicit counter even though there is the extra unpack, and you still need to initialize the counter in the general case: for i, item in enumerate([]): pass print(f"There are {i+1} items in the list.") # Oops > English language 'treachery': > - one die > - multiple dice You might have inferred that I knew (or had looked up) the singular of dice, so this is but a momentary lapse of reason. It hurts me more than you, trust me. Not as much, as going on record with confusing they're and their, but still ;) > (probably not followed in US-English (can't recall), particularly on > computers running the Hollywood Operating System). I've come to the conclusion that International English is hopelessly and inevitably broken. That's the price native speakers have to pay for having they're (oops, I did it again!) language used as lingua franca. > Continuous Education: > Thanks for the reminder that enumerate() can be seeded with a "start" value! [1] I think I've suggested reimplementing the whole module in terms of generators -- can't find the post though. From joepareti54 at gmail.com Sun Aug 29 14:44:53 2021 From: joepareti54 at gmail.com (joseph pareti) Date: Sun, 29 Aug 2021 20:44:53 +0200 Subject: code to initialize a sequence Message-ID: In the code attached below, the A-variant is from somebody else who knows Python better than I. But I do not like to just use any code without having a grasp, specifically the line in* bold*, so I wrote the B-variant which gives the same results. The C-variant is identical to A and is there for verification: after resetting the seed I expect the same sequence. The D-variant is closer to the way I code, and it does not work. import random from random import randint, seed def generate_sequence(length, n_unique): *return [randint(0, n_unique-1) for k in range(length)]* def generate_sequence_JP(length, n_unique): LI = [] for k in range(length): LI.append(randint(0, n_unique-1)) return(LI) def generate_sequence_EXPLICIT(length, n_unique): X =[None] * length for i in range(length): X[i] = [randint(0, n_unique-1)] return X # # MAIN PROGRAM # random.seed(2) A = generate_sequence(4, 10 ) random.seed(2) B = generate_sequence_JP(4, 10) random.seed(2) C = generate_sequence(4, 10 ) random.seed(2) D = generate_sequence_EXPLICIT(4, 10 ) print(A) print(type(A)) print('-----------------------------') print(B) print(type(B)) print('-----------------------------') print(C) print(type(C)) print('-----------------------------') print(D) print(type(D)) Regards, Joseph Pareti - Artificial Intelligence consultant Joseph Pareti's AI Consulting Services https://www.joepareti54-ai.com/ cell +49 1520 1600 209 cell +39 339 797 0644 From __peter__ at web.de Sun Aug 29 15:15:03 2021 From: __peter__ at web.de (Peter Otten) Date: Sun, 29 Aug 2021 21:15:03 +0200 Subject: code to initialize a sequence In-Reply-To: References: Message-ID: On 29/08/2021 20:44, joseph pareti wrote: > In the code attached below, the A-variant is from somebody else who knows > Python better than I. But I do not like to just use any code without having > a grasp, specifically the line in* bold*, so I wrote the B-variant which > gives the same results. The C-variant is identical to A and is there for > verification: after resetting the seed I expect the same sequence. The > D-variant is closer to the way I code, and it does not work. So you do you want us to debug the _EXPLICIT version? The assignment > X[i] = [randint(0, n_unique-1)] creates a list with one element and turns it into an item in the list X. You don't want a list, you want the numerical value, the straight-forward way to achieve that being X[i] = randint(0, n_unique-1) An alternative is to assign to a slice X[i:i+1] = [randint(...)] but that would only make sense if the right-hand-side list weren't created in the line and ditched immediately afterwards. > > > import random > from random import randint, seed > > def generate_sequence(length, n_unique): > *return [randint(0, n_unique-1) for k in range(length)]* The above is the most pythonic of the three versions. Once you understand how for loops with a list.append() are turned into comprehensions it will be easy to write and read that style. Definitely worth learning and adopting. > > def generate_sequence_JP(length, n_unique): > LI = [] > for k in range(length): > LI.append(randint(0, n_unique-1)) > return(LI) This is also fine and often used when the loop body is a bit more complex, but > def generate_sequence_EXPLICIT(length, n_unique): > X =[None] * length > for i in range(length): > X[i] = [randint(0, n_unique-1)] > return X this is garbage even when it works, usually indicative of premature optimization. Random (yeah!) remark: Python uses half-open intervals (i. e. intervals that include the lower bound, but not the upper bound) almost everywhere. randint() is one exception. Personally I prefer its conformist sister randrange(); with that randint(0, n_unique-1) becomes randrange(n_unique) > # > # MAIN PROGRAM > # > random.seed(2) > A = generate_sequence(4, 10 ) > random.seed(2) > B = generate_sequence_JP(4, 10) > random.seed(2) > C = generate_sequence(4, 10 ) > random.seed(2) > D = generate_sequence_EXPLICIT(4, 10 ) > print(A) > print(type(A)) > print('-----------------------------') > print(B) > print(type(B)) > print('-----------------------------') > print(C) > print(type(C)) > print('-----------------------------') > print(D) > print(type(D)) > > > Regards, > Joseph Pareti - Artificial Intelligence consultant > Joseph Pareti's AI Consulting Services > https://www.joepareti54-ai.com/ > cell +49 1520 1600 209 > cell +39 339 797 0644 > From george at fischhof.hu Sun Aug 29 15:27:24 2021 From: george at fischhof.hu (George Fischhof) Date: Sun, 29 Aug 2021 21:27:24 +0200 Subject: Making command-line args available to deeply-nested functions In-Reply-To: <87sfyw7cvn.fsf@hornfels.zedat.fu-berlin.de> References: <87czq8tpay.fsf@hornfels.zedat.fu-berlin.de> <230149ee-f6ed-4e2f-8ac3-c12388ca45acn@googlegroups.com> <878s0wtljf.fsf@hornfels.zedat.fu-berlin.de> <87sfz0y0gx.fsf@hornfels.zedat.fu-berlin.de> <87sfyw7cvn.fsf@hornfels.zedat.fu-berlin.de> Message-ID: Loris Bennett ezt ?rta (id?pont: 2021. aug. 26., Cs, 16:02): > George Fischhof writes: > > [snip (79 lines)] > > >> > Hi, > >> > > >> > Also you can give a try to click and / or typer packages. > >> > Putting args into environment variables can be a solution too > >> > All of these depends on several things: personal preferences, > colleagues > >> / > >> > firm standards, the program, readability, variable accessibility (IDE > >> > support, auto completition) (env vars not supported by IDEs as they > are > >> not > >> > part of code) > >> > >> Thanks for the pointers, although I have only just got my head around > >> argparse/configargparse, so click is something I might have a look at > >> for future project. > >> > >> However, the question of how to parse the arguments is somewhat separate > >> from that of how to pass (or not pass) the arguments around within a > >> program. > > [snip (16 lines)] > > > > Hi, > > I thought not just parsing, but the usage method: you add a decorator to > > the function where you want to use the parameters. This way you do not > have > > to pass the value through the calling hierarchy. > > > > Note: typer is a newer package, it contains click and leverages command > > line parsing even more. > > Do you have an example of how this is done? From a cursory reading of > the documentation, it didn't seem obvious to me how to do this, but then > I don't have much understanding of how decorators work. > > Cheers, > > Loris > > > -- > This signature is currently under construction. > -- > https://mail.python.org/mailman/listinfo/python-list Hi, will create a sample code on Monday - Tuesday BR, George From mehrzad.1024 at gmail.com Sun Aug 29 15:47:26 2021 From: mehrzad.1024 at gmail.com (Mehrzad Saremi) Date: Mon, 30 Aug 2021 00:17:26 +0430 Subject: PEP Idea: Real private attribute In-Reply-To: References: Message-ID: No, a class ("the class that I'm lexically inside") cannot be accessed from outside of the class. This is why I'm planning to offer it as a core feature because only the parser would know. There's apparently no elegant solution if you want to implement it yourself. You'll need to write self.__privs__[__class__, "foo"], whenever you want to use the feature and even wrapping it in superclasses won't remedy it, because the parent class isn't aware which class you're inside. It seems to me name mangling must have been an ad-hoc solution in a language that it doesn't really fit when it could have been implemented in a much more cogent way. Best, [image: image.gif][image: image.gif] Mehrzad On Sun, 29 Aug 2021 at 02:18, Chris Angelico wrote: > On Sun, Aug 29, 2021 at 7:40 AM Mehrzad Saremi > wrote: > > > > Python currently uses name mangling for double-underscore attributes. > Name > > mangling is not an ideal method to avoid name conflicting. There are > > various normal programming patterns that can simply cause name > conflicting > > in double-underscore members. A typical example is when a class is > > re-decorated using the same decorator. The decorator can not take > > double-underscore members without name conflicts. For example: > > > > ``` > > @custom_decorator("a") > > @custom_decorator("b") > > class C: > > pass > > ``` > > > > The `@custom_decorator` wrapper may need to hold private members, but > > Python's current name conflict resolution does not provide any solution > and > > the decorator cannot hold private members without applying tricky > > programming methods. > > > > Another example is when a class inherits from a base class of the same > name. > > > > ``` > > class View: > > """A class representing a view of an object; similar to > > numpy.ndarray.view""" > > pass > > > > class Object: > > class View(View): > > """A view class costumized for objects of type Object""" > > pass > > ``` > > > > Again, in this example, class `Object.View` can't take double-underscore > > names without conflicting with `View`'s. > > > > My idea is to introduce real private members (by which I do not mean to > be > > inaccessible from outside the class, but to be guaranteed not to conflict > > with other private members of the same object). These private members are > > started with triple underscores and are stored in a separate dictionary > > named `__privs__`. Unlike `__dict__` that takes 'str' keys, `__privs__` > > will be a double layer dictionary that takes 'type' keys in the first > > level, and 'str' keys in the second level. > > > > For example, assume that the user runs the following code: > > ``` > > class C: > > def __init__(self, value): > > self.___member = value > > > > c = C("my value") > > ``` > > > > On the last line, Python's attribute setter creates a new entry in the > > dictionary with key `C`, adds the value "my value" to a new entry with > the > > key 'member'. > > > > The user can then retrieve `c.___member` by invoking the `__privs__` > > dictionary: > > > > ``` > > print(c.__privs__[C]['member']) # prints 'my value' > > ``` > > > > Note that, unlike class names, class objects are unique and there will > not > > be any conflicts. Python classes are hashable and can be dictionary keys. > > Personally, I do not see any disadvantage of using __privs__ over name > > mangling/double-underscores. While name mangling does not truly guarantee > > conflict resolution, __privs__ does. > > Not entirely sure how it would know the right type to use (subclassing > makes that tricky), but whatever your definition is, there's nothing > stopping you from doing it yourself. Don't forget that you have > __class__ available if you need to refer to "the class that I'm > lexically inside" (that's how the zero-arg super() function works), so > you might do something like self.__privs__[__class__, "foo"] to refer > to a thing. > > ChrisA > -- > https://mail.python.org/mailman/listinfo/python-list > From rosuav at gmail.com Sun Aug 29 15:56:32 2021 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 30 Aug 2021 05:56:32 +1000 Subject: PEP Idea: Real private attribute In-Reply-To: References: Message-ID: On Mon, Aug 30, 2021 at 5:49 AM Mehrzad Saremi wrote: > > No, a class ("the class that I'm lexically inside") cannot be accessed from > outside of the class. This is why I'm planning to offer it as a core > feature because only the parser would know. There's apparently no elegant > solution if you want to implement it yourself. You'll need to write > self.__privs__[__class__, "foo"], whenever you want to use the feature and > even wrapping it in superclasses won't remedy it, because the parent class > isn't aware which class you're inside. It seems to me name mangling must > have been an ad-hoc solution in a language that it doesn't really fit when > it could have been implemented in a much more cogent way. > If the parent class isn't aware which class you're in, how is the language going to define it? Can you give a full run-down of the semantics of your proposed privs, and how it's different from something like you just used above - self.__privs__[__class__, "foo"] - ? If the problem is the ugliness alone, then say so; but also, how this would work with decorators, since you specifically mention them as a use-case. ChrisA From PythonList at DancesWithMice.info Sun Aug 29 19:52:18 2021 From: PythonList at DancesWithMice.info (dn) Date: Mon, 30 Aug 2021 11:52:18 +1200 Subject: on writing a while loop for rolling two dice In-Reply-To: References: <86r1edlqxw.fsf@jevedi.com> Message-ID: On 29/08/2021 22.24, Chris Angelico wrote: > On Sun, Aug 29, 2021 at 8:14 PM dn via Python-list > wrote: >> Efficiency: >> - wonder how max( d ) == min( d ) compares for speed with the set() type >> constructor? > > That may or may not be an improvement. > >> - alternately len( d ) < 2? >> - or len( d ) - 1 coerced to a boolean by the if? > > Neither of these will make any notable improvement. The work is done > in constructing the set, and then you're taking the length. How you do > the comparison afterwards is irrelevant. It was far too late for either of us (certainly this little boy) to be out-and-coding - plus an excellent illustration of why short-names are a false-economy which can quickly (and easily) lead to "technical debt"! The "d" is a tuple (the 'next' returned from the zip-output object) consisting of a number of die-throw results). Thus, can toss that into len() without (any overhead of) conversion to a set. -- Regards, =dn From rosuav at gmail.com Sun Aug 29 19:58:12 2021 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 30 Aug 2021 09:58:12 +1000 Subject: on writing a while loop for rolling two dice In-Reply-To: References: <86r1edlqxw.fsf@jevedi.com> Message-ID: On Mon, Aug 30, 2021 at 9:53 AM dn via Python-list wrote: > > On 29/08/2021 22.24, Chris Angelico wrote: > > On Sun, Aug 29, 2021 at 8:14 PM dn via Python-list > > wrote: > >> Efficiency: > >> - wonder how max( d ) == min( d ) compares for speed with the set() type > >> constructor? > > > > That may or may not be an improvement. > > > >> - alternately len( d ) < 2? > >> - or len( d ) - 1 coerced to a boolean by the if? > > > > Neither of these will make any notable improvement. The work is done > > in constructing the set, and then you're taking the length. How you do > > the comparison afterwards is irrelevant. > > It was far too late for either of us (certainly this little boy) to be > out-and-coding - plus an excellent illustration of why short-names are a > false-economy which can quickly (and easily) lead to "technical debt"! > > > The "d" is a tuple (the 'next' returned from the zip-output object) > consisting of a number of die-throw results). Thus, can toss that into > len() without (any overhead of) conversion to a set. Oh. Well, taking the length of the tuple is fast... but useless. The point was to find out if everything in it was unique :) Conversion to set tests this because the length of the set is the number of unique elements; checking max and min works because two scans will tell you if they're all the same; using all with a generator stops early if you find a difference, but requires back-and-forth calls into Python code; there are various options, and the choice probably won't make a material performance difference anyway :) ChrisA From mehrzad.1024 at gmail.com Sun Aug 29 21:08:11 2021 From: mehrzad.1024 at gmail.com (Mehrzad Saremi) Date: Mon, 30 Aug 2021 05:38:11 +0430 Subject: PEP Idea: Real private attribute In-Reply-To: References: Message-ID: The proposed semantics would be the same as self.__privs__[__class__, "foo"]; yes I can say the problem is ugliness. The following is an example where name mangling can be problematic (of course there are workarounds, yet if double-underscores are meant to represent class-specific members, the following behavior is an infringement of the purpose). ``` class Weighable: def weight(self): raise NotImplementedError() class AddWeight: def __init__(self, weight): self.weight = weight def __call__(self, cls): class Wrapper(cls, Weighable): __weight = self.weight def weight(self): return self.__weight + (cls.weight(self) if issubclass(cls, Weighable) else 0) # Unexpected behavior return Wrapper @AddWeight(2.0) @AddWeight(1.0) class C: pass print(C().weight()) ``` > If the parent class isn't aware which class you're in, how is the language going to define it? I mean if you want to implement self.__privs__[__class__, "foo"] in a parent class using __setattr__/__getattribute__ the __class__ value is unknown. On Mon, 30 Aug 2021 at 00:26, Chris Angelico wrote: > On Mon, Aug 30, 2021 at 5:49 AM Mehrzad Saremi > wrote: > > > > No, a class ("the class that I'm lexically inside") cannot be accessed > from > > outside of the class. This is why I'm planning to offer it as a core > > feature because only the parser would know. There's apparently no elegant > > solution if you want to implement it yourself. You'll need to write > > self.__privs__[__class__, "foo"], whenever you want to use the feature > and > > even wrapping it in superclasses won't remedy it, because the parent > class > > isn't aware which class you're inside. It seems to me name mangling must > > have been an ad-hoc solution in a language that it doesn't really fit > when > > it could have been implemented in a much more cogent way. > > > > If the parent class isn't aware which class you're in, how is the > language going to define it? > > Can you give a full run-down of the semantics of your proposed privs, > and how it's different from something like you just used above - > self.__privs__[__class__, "foo"] - ? If the problem is the ugliness > alone, then say so; but also, how this would work with decorators, > since you specifically mention them as a use-case. > > ChrisA > -- > https://mail.python.org/mailman/listinfo/python-list > From PythonList at DancesWithMice.info Mon Aug 30 00:17:12 2021 From: PythonList at DancesWithMice.info (dn) Date: Mon, 30 Aug 2021 16:17:12 +1200 Subject: on writing a while loop for rolling two dice In-Reply-To: References: <86r1edlqxw.fsf@jevedi.com> Message-ID: <6fcf22af-fbf8-7a7b-4123-16765d431758@DancesWithMice.info> On 30/08/2021 00.47, Peter Otten wrote: > On 29/08/2021 12:13, dn via Python-list wrote: >> On 29/08/2021 20.06, Peter Otten wrote: >> ... >>> OK, maybe a bit complicated... but does it pay off if you want to >>> generalize? >>> >>>>>> def roll_die(faces): >>> ?????while True: yield random.randrange(1, 1 + faces) >>> >>>>>> def hmt(faces, dies): >>> ?????for c, d in enumerate(zip(*[roll_die(faces)]*dies), 1): >>> ???????? if len(set(d)) == 1: return c, d >> >> >> Curiosity: >> why not add dies as a parameter of roll_die()? > > Dunno. Maybe because I've "always" [1] wanted a version of > random.randrange() that generates values indefinitely. It would need to > check its arguments only once, thus leading to some extra Each code-unit should do one job, and do it well! SRP... >> Efficiency: >> - wonder how max( d ) == min( d ) compares for speed with the set() type >> constructor? > > I did the simplest thing, speed was not a consideration. If it is, and > dies (sorry for that) is large I'd try > > first = d[0] > all(x == first for x in d)? # don't mind one duplicate test > > For smaller numbers of dice I'd unpack (first, *rest) inside the for > loop. But it's a trade-off, you' have to measure if/when it's better to > go through the whole tuple in C. For larger numbers of dice, and presuming a preference for an inner-function which rolls only a single die per call; would it be more efficient to test each individual die's value against the first, immediately after its (individual) roll/evaluation (rinse-and-repeat for each die thereafter)? This, on the grounds that the first mis-match obviates the need to examine (or even roll), any other die/dice in the collection. OTOH the simulation of rolling n-number of dice, as would happen in the real-world, would be broken by making the computer's algorithm more efficient (rolling until the first non-equal value is 'found'). Does that mean the realism of the model dies? (sorry - no, I'm not sorry - you deserved that!) Does one "roll" a die, or "shake the dice"??? We don't know the OP's requirements wrt to execution-efficiency. However, as you (also) probably suffered, such exercises regularly feature in stats and probability courses. Sometimes 'the numbers' are quite large in order to better-illustrate ("smooth") distribution characteristics, etc. I have a love?hate relationship with questions of Python and 'efficiency'. Today, discovered that using a cut-down Linux version (on AWS) was actually slower than using a full-fat distribution - upon analysis, my friendly 'expert' was able to point the finger at the way the two distros compiled/prepared/distribute the(ir) Python Interpreter. (I'm glad he thought such investigation 'fun'!) All of which further complicates the business of design, given we already know of situations where approach-a will run faster than approach-b, on your machine; yet the comparison may be reversed on mine. This discussion forms a sub-set of that: when to use the built-in functions (implemented in C) because they are (claimed to be) more efficient than another approach - and, when one approach using a built-in function might be faster than another 'built-in'/C-coded approach. ("small things amuse small minds" - mind how you describe my mind!) "Bottom line": I prefer to think of Python's "efficiency" as reflected in the amount of my time that is needed, in order to complete a project! >> - alternately len( d ) < 2? >> - or len( d ) - 1 coerced to a boolean by the if? >> - how much more efficient is any of this (clever thinking!) than the >> OP's basic, simpler, and thus more readable, form? > > It really isn't efficiency, it's a (misled?) sense of aesthetics where > I've come to prefer > > - for-loops over while, even when I end up with both to get the desired for > > - enumerate() over an explicit counter even though there is the extra > unpack, and you still need to initialize the counter in the general case: > > for i, item in enumerate([]): pass > print(f"There are {i+1} items in the list.")? # Oops Next thing you'll be using for-else... [insane giggling] It's interesting how we arrive at these views (as a trainer I spend a lot of time trying to detect how learners build their mental maps, or "models", of each topic). I've always had a clear 'formula'/rule/hobgoblin: if the number of loops can be predicted, use 'for', otherwise use 'while'. Of course, Python alters that view because it offers a for-each, which means that I don't need to know the number of loops, only that the loop will cycle through each item in the iterable. It used to be a far simpler world! That said, I really miss the option of while controlling the loop with a pre-condition AND having a repeat...until controlling the loop with a post-condition - the former enabling >=0 loops; the latter, requiring at least one! Using enumerate() may be a matter of aesthetics (English-English spelling!). However, it is a basic Python idiom. It is as much a tool in our coding as a fork/spoon/chop-sticks/fingers are to someone eating. (yes, I'm feeling hungry). At times I feel a 'siren call' to use some of the powerful, let's call them "one-liner" tools, because it is 'fun' to bend my mind around the challenge. However, most such code tends to lose readability in some sort of inverse proportion to its power - it leaves the clarity and simplicity of Python-space and heads towards APL, Lisp, et al. The 'problem' is that as a coder increases his/her knowledge (learns to harness 'the force'), the code-structures which count as one "chunk" of thought, expand. For example, it can be difficult to see (remember) that although comprehensions may have become a single 'unit' of thought to a skilled practitioner; for others they are (still) opaque, and 'mountains' to climb. Thus, the 'balance' between 'power' and readability; and between using techniques which demand Python-expertise and thus carry an expectation that less-capable/-experienced programmers will 'improve their game' (to be able to contribute to 'this' project, or future re-use/maintenance). (see also "Zen of Python") The 'level' then becomes a convention - just as much as 'do we adhere to PEP-008 naming' (etc). The important point is not what the convention is, but that the team has arrived at a pragmatic agreement, eg will we use comprehensions or explicit loops. Your team might say "of course", whereas mine says "can't cope with that"... BTW you already know this, but I'm not writing only to you! (don't fret, you're still 'special'...) >> English language 'treachery': >> - one die >> - multiple dice > > You might have inferred that I knew (or had looked up) the singular of > dice, so this is but a momentary lapse of reason. It hurts me more than > you, trust me. Not as much, as going on record with confusing they're > and their, but still ;) Reason? Logic? Consistency? The English language. Surely, you jest... Having learned/lived many languages, struggling-mightily with some, feeling comfortable with others; I am enormously grateful (greatly grateful?) that English was one of my home-languages, and that I didn't have to "learn" it! I do enjoy 'playing' with it though, and as pointed-out annually (?semesterly), making students groan in response to my weak/pathetic/Dad-joke/seven-year-old's humor (in live-lectures) at least gives feedback that they are 'there' and paying some attention. (alternately, it's Pavlovian-conditioning - BTW: yes, I'm still hungry...) Please consider the die/dice as 'educational', and a reflection of my confusion of comprehension when trying to infer meaning whilst reading the code-example - rather than arrogance or placing undue demand on you. >> (probably not followed in US-English (can't recall), particularly on >> computers running the Hollywood Operating System). > > I've come to the conclusion that International English is hopelessly and > inevitably broken. That's the price native speakers have to pay for > having they're (oops, I did it again!) language used as lingua franca. If English really set-out to be the world's lingua-franca, why didn't it come up with its own, a particularly (and peculiarly) English word, for the concept??? I've spent quite some time looking into the idea of 'International English' - to attempt to find 'an English' to employ in our course materials used world-wide. Even 'native speakers' can't agree on what is 'English'! When the question is widened to include the broader, majority of the world; the concept of a 'core' of English becomes impossible to define or encapsulate... Even being a 'native speaker' doesn't necessarily help: George Bernard Shaw described "Britain and America are two nations divided by [the use of] a common language"! He was Irish - and I recall another quotation along the lines of: the Irish learn English in order to hurl insults. Sigh! Let's not be racist though - or would that be lingual-ist(?) Advice when learning French was "always expect exceptions" (apologies, I went looking for a source, in English or French - but Python-references crowded the first couple of web-search 'hits'). I enjoy the word-picture in Spanish: "Hijo de tigre, no siempre sale pintado. Siempre ahi esa excepci?n." (The tiger-cub isn't always born (ready-)painted (colored?striped). There is always an exception!) So much more apropos (to use another (?)English expression) than, that "a leopard NEVER changes its spots"! >> Continuous Education: >> Thanks for the reminder that enumerate() can be seeded with a "start" >> value! > > [1] I think I've suggested reimplementing the whole module in terms of > generators -- can't find the post though. Can't we assume lazy-evaluation - if only by virtue of the example equivalent-code illustration in the docs? (it features a "yield") (https://docs.python.org/3/library/functions.html?highlight=enumerate#enumerate) Must admit, once the use of generators started to multiply release-after-release (both in Python code and 'under the hood'), and tools like range()/xrange() were made more memory-efficient, etc, that pretty much all such constructs had become "lazy". (Careless assumption. Don't know!) -- Regards, =dn From David.Raymond at tomtom.com Mon Aug 30 09:11:53 2021 From: David.Raymond at tomtom.com (David Raymond) Date: Mon, 30 Aug 2021 13:11:53 +0000 Subject: on writing a while loop for rolling two dice In-Reply-To: <86r1edlqxw.fsf@jevedi.com> References: <86r1edlqxw.fsf@jevedi.com> Message-ID: > def how_many_times(): > x, y = 0, 1 > c = 0 > while x != y: > c = c + 1 > x, y = roll() > return c, (x, y) Since I haven't seen it used in answers yet, here's another option using our new walrus operator def how_many_times(): roll_count = 1 while (rolls := roll())[0] != rolls[1]: roll_count += 1 return (roll_count, rolls) From rosuav at gmail.com Mon Aug 30 09:50:27 2021 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 30 Aug 2021 23:50:27 +1000 Subject: on writing a while loop for rolling two dice In-Reply-To: References: <86r1edlqxw.fsf@jevedi.com> Message-ID: On Mon, Aug 30, 2021 at 11:13 PM David Raymond wrote: > > > def how_many_times(): > > x, y = 0, 1 > > c = 0 > > while x != y: > > c = c + 1 > > x, y = roll() > > return c, (x, y) > > Since I haven't seen it used in answers yet, here's another option using our new walrus operator > > def how_many_times(): > roll_count = 1 > while (rolls := roll())[0] != rolls[1]: > roll_count += 1 > return (roll_count, rolls) > Since we're creating solutions that use features in completely unnecessary ways, here's a version that uses collections.Counter: def how_many_times(): return next((count, rolls) for count, rolls in enumerate(iter(roll, None)) if len(Counter(rolls)) == 1) Do I get bonus points for it being a one-liner that doesn't fit in eighty characters? ChrisA From __peter__ at web.de Mon Aug 30 10:20:16 2021 From: __peter__ at web.de (Peter Otten) Date: Mon, 30 Aug 2021 16:20:16 +0200 Subject: on writing a while loop for rolling two dice In-Reply-To: References: <86r1edlqxw.fsf@jevedi.com> Message-ID: On 30/08/2021 15:50, Chris Angelico wrote: > def how_many_times(): > return next((count, rolls) for count, rolls in > enumerate(iter(roll, None)) if len(Counter(rolls)) == 1) That's certainly the most Counter-intuitive version so far;) > Do I get bonus points for it being a one-liner that doesn't fit in > eighty characters? Nah, but you'll get an honorable mention when you run it through pycodestyle without line break... From rosuav at gmail.com Mon Aug 30 10:31:45 2021 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 31 Aug 2021 00:31:45 +1000 Subject: on writing a while loop for rolling two dice In-Reply-To: References: <86r1edlqxw.fsf@jevedi.com> Message-ID: On Tue, Aug 31, 2021 at 12:28 AM Peter Otten <__peter__ at web.de> wrote: > > On 30/08/2021 15:50, Chris Angelico wrote: > > > def how_many_times(): > > return next((count, rolls) for count, rolls in > > enumerate(iter(roll, None)) if len(Counter(rolls)) == 1) > > > That's certainly the most Counter-intuitive version so far;) Thank you, I appreciate that :) > > Do I get bonus points for it being a one-liner that doesn't fit in > > eighty characters? > > Nah, but you'll get an honorable mention when you run it through > pycodestyle without line break... > Are there any linters that warn against "unintuitive use of two-argument iter()"? ChrisA From __peter__ at web.de Mon Aug 30 10:33:51 2021 From: __peter__ at web.de (Peter Otten) Date: Mon, 30 Aug 2021 16:33:51 +0200 Subject: on writing a while loop for rolling two dice In-Reply-To: <6fcf22af-fbf8-7a7b-4123-16765d431758@DancesWithMice.info> References: <86r1edlqxw.fsf@jevedi.com> <6fcf22af-fbf8-7a7b-4123-16765d431758@DancesWithMice.info> Message-ID: On 30/08/2021 06:17, dn via Python-list wrote: > OTOH the simulation of rolling n-number of dice, as would happen in the > real-world, would be broken by making the computer's algorithm more > efficient (rolling until the first non-equal value is 'found'). Does > that mean the realism of the model dies? You've got to ask your dietician... (I'm sure everyone agrees that I should stop here. And stop I will) From arj.python at gmail.com Mon Aug 30 14:41:20 2021 From: arj.python at gmail.com (Abdur-Rahmaan Janhangeer) Date: Mon, 30 Aug 2021 22:41:20 +0400 Subject: Setup.py + src: Modules not found Message-ID: Greetings list, I have this project: https://github.com/pyhoneybot/honeybot I badly wanted to use setup.cfg but editable mode is not allowed for now. I then switched back to setup.py. This is my first time with src/, my entry point is src/honeybot/manage.py:main now in editable mode i manage to get everything to work however, when installing from tar.gz i get from honeybot.api.main import Bot_core ModuleNotFoundError: No module named 'honeybot.api' like i have a hard time getting how exactly to import with src/ i guess everything was working as when i changed to honeybot.x, the package was installed but on a fresh release, it does not know what exactly is honeybot for the first time Q: In my case in modules what should i write to import from /api? Kind Regards, Abdur-Rahmaan Janhangeer about | blog github Mauritius From wlfraed at ix.netcom.com Sun Aug 29 15:42:52 2021 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Sun, 29 Aug 2021 15:42:52 -0400 Subject: code to initialize a sequence References: Message-ID: On Sun, 29 Aug 2021 20:44:53 +0200, joseph pareti declaimed the following: >In the code attached below, the A-variant is from somebody else who knows >Python better than I. But I do not like to just use any code without having >a grasp, specifically the line in* bold*, so I wrote the B-variant which >gives the same results. The C-variant is identical to A and is there for >verification: after resetting the seed I expect the same sequence. The >D-variant is closer to the way I code, and it does not work. > > >import random >from random import randint, seed > >def generate_sequence(length, n_unique): >*return [randint(0, n_unique-1) for k in range(length)]* This does NOT ensure length_UNIQUE values. With a bad seed, it could be possible to return length IDENTICAL values. If you really need unique values, I suggest return random.sample(range(n_unique), k=length) which handles both the range of values, and ensures the subset selected is all unique. """ Generate n unique samples (multiple items) from a sequence without repetition. Here, A seq can be a list, set, string, tuple. Sample without replacement. """ > >def generate_sequence_JP(length, n_unique): > LI = [] > for k in range(length): > LI.append(randint(0, n_unique-1)) > return(LI) Again, nothing is checking for UNIQUE values... LI = [] while len(LI) < length: #untested, may need length - 1 ri = randint(0, n_unique-1) if ri not in LI: LI.append(ri) >def generate_sequence_EXPLICIT(length, n_unique): > X =[None] * length > for i in range(length): > X[i] = [randint(0, n_unique-1)] > return X Same -- nothing about UNIQUE values. Prefilling a list with None, just to immediate replace all the values feels "unPythonic". -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From loris.bennett at fu-berlin.de Mon Aug 30 02:14:18 2021 From: loris.bennett at fu-berlin.de (Loris Bennett) Date: Mon, 30 Aug 2021 08:14:18 +0200 Subject: configargparse - reading option from config only References: <87lf4o7ce2.fsf@hornfels.zedat.fu-berlin.de> <87mtp3jq2h.fsf@hornfels.zedat.fu-berlin.de> <9976b879-98cd-5a2b-5394-e42923334948@Damon-Family.org> Message-ID: <87y28j8nnp.fsf@hornfels.zedat.fu-berlin.de> Richard Damon writes: > On 8/27/21 3:37 AM, Loris Bennett wrote: >> Richard Damon writes: >> >>> On 8/26/21 6:01 AM, Loris Bennett wrote: >>>> Hi, >>>> >>>> When using configargparse, it seems that if a value is to be read from a >>>> config file, it also has to be defined as a command-line argument in >>>> order to turn up as an attribute in the parser namespace. >>>> >>>> I can sort of see why this is the case, but there are also some options >>>> I would like to read just from the config file and not have them >>>> available as command-line options. This would be, say, to prevent the >>>> number of options on the command-line from becoming bloated by >>>> little-used settings. >>>> >>>> Is there an elegant way to do this? >>>> >>>> Cheers, >>>> >>>> Loris >>>> >>> Look at the read() member function to supply the file name to read. Then >>> in the config object there will be sections for each section in the >>> config file. No need for any of these to be 'options' >> Do you have a link for this? As far as I can see, the config files are >> given in the following manner: >> >> p = configargparse.ArgParser(default_config_files=['/etc/app/conf.d/*.conf', '~/.my_settings']) >> >> I can obviously just read the config file with configparser, but the >> idea of configargparse is that an option can be specified as an option, >> in a config file, or as an environment variable, >> >> As far as I can tell, configargparse only loads entries from the config >> file into the appropriate namespace if they have also been defined as >> long options (i.e. with '--'). I was hoping to access *all* the config >> file entries, regardless of whether they are also options, since the >> config is obviously being read. >> >> Cheers, >> >> Loris >> > I misread your question, I thought you were talking about configparse. > > Question is, if configargparse doesn't do what you want, then it isn't > the right tool. > > It looks like configargparse is SPECIFICALLY designed to allow the use > to use a file as a shorthand to present command line arguements. The > whole parsing structure is based on an enumerated set of options, if > that isn't what you have, it is the wrong tool. I am not sure what you mean by using a file as a shorthand to present command line arguements since the command-line arguments are defined by caling the 'add_argument' method of the configargparse object. However, I agree with your analysis that configargparse is the wrong tool for what I want to do. I like the idea that a variable can be defined as a command-line option, an entry in a config file, or as an environment variable. However, when I think about it, it seems that command-line options are essentially different from parameters in a configuration file, not least because the former need some sort of description for the output of '--help', whereas the latter do not. Cheers, Loris -- This signature is currently under construction. From hongyi.zhao at gmail.com Sun Aug 29 22:49:19 2021 From: hongyi.zhao at gmail.com (hongy...@gmail.com) Date: Sun, 29 Aug 2021 19:49:19 -0700 (PDT) Subject: The sqlite3 timestamp conversion between unixepoch and localtime can't be done according to the timezone setting on the machine automatically. Message-ID: <715e310e-56e3-4c97-a454-770c709ea706n@googlegroups.com> On Ubuntu 20.04.2 LTS, I use the [recent2](https://github.com/dotslash/recent2/blob/master/recent2.py) to log and query my bash history, which uses a sqlite3 database to store the history information. The `datetime` of running a command is inserted in the sqlite3 database with [a `unixepoch` format](https://github.com/dotslash/recent2/blob/f1018aee228c710cc7d1b8b93bc0228791a54563/recent2.py#L45), and it will be converted into `localtime` accordingly when retrieved and displayed later. But I found that it did not perform the correct conversion according to the time zone setting on the machine, as shown below: ```shell werner at X10DAi-00:~$ rm 222222222222222222 rm: cannot remove '222222222222222222': No such file or directory werner at X10DAi-00:~$ recent -fo -w . 2222222222222 rm 222222222222222222 # rtime@ 2021-08-29 10:57:13 werner at X10DAi-00:~$ date Sun 29 Aug 2021 06:57:22 PM CST ``` I also filed an issue [here](https://discuss.python.org/t/python-sqlite3-datetime-verconsion-between-unixepoch-and-localtime/10382). Any hints for this problem? Regards, HY From rlozanovalle14 at gmail.com Mon Aug 30 11:37:26 2021 From: rlozanovalle14 at gmail.com (randy darwin lozanovalle) Date: Mon, 30 Aug 2021 10:37:26 -0500 Subject: software installation problems Message-ID: Good morning, when I run the Python program after installing the latest version, I get this message (attached file), I have already reinstalled the program several times and the same message keeps appearing; What solution could you give me, thank you! From hariharan1995.senthil at gmail.com Sun Aug 29 06:28:23 2021 From: hariharan1995.senthil at gmail.com (Hari) Date: Sun, 29 Aug 2021 15:58:23 +0530 Subject: urgent Message-ID: i was download ur python software but it is like boring user interface for me like young student to learn ,can u have any updates? From ikorot01 at gmail.com Mon Aug 30 17:38:27 2021 From: ikorot01 at gmail.com (Igor Korot) Date: Mon, 30 Aug 2021 16:38:27 -0500 Subject: urgent In-Reply-To: References: Message-ID: Hi, On Mon, Aug 30, 2021 at 4:34 PM Hari wrote: > > i was download ur python software but it is like boring user interface for > me like young student to learn ,can u have any updates? Can you elaborate a little: Why do you want python? What task do you want to solve with python? Why python? Why not any other language? Thank you. > -- > https://mail.python.org/mailman/listinfo/python-list From ikorot01 at gmail.com Mon Aug 30 17:39:37 2021 From: ikorot01 at gmail.com (Igor Korot) Date: Mon, 30 Aug 2021 16:39:37 -0500 Subject: software installation problems In-Reply-To: References: Message-ID: Hi, On Mon, Aug 30, 2021 at 4:37 PM randy darwin lozanovalle wrote: > > Good morning, when I run the Python program after installing the > latest version, I get this message (attached file), I have already > reinstalled the program several times and the same message keeps > appearing; What solution could you give me, thank you! This is "no-attachment" list. Please copy and paste the error inside the message body. Thank you. > -- > https://mail.python.org/mailman/listinfo/python-list From lukasz at langa.pl Mon Aug 30 18:36:51 2021 From: lukasz at langa.pl (=?utf-8?Q?=C5=81ukasz_Langa?=) Date: Tue, 31 Aug 2021 00:36:51 +0200 Subject: [RELEASE] Python 3.9.7 and 3.8.12 are now available Message-ID: <08CDAABF-6E14-40D7-8610-25216BD87CD3@langa.pl> Python 3.9.7 Get it here: https://www.python.org/downloads/release/python-397/ Python 3.9.7 is the newest major stable release of the Python programming language, and it contains many new features and optimizations. There?s been 187 commits since 3.9.6 which is a similar amount compared to 3.8 at the same stage of the release cycle. See the change log for details. On macOS, we encourage you to use the universal2 binary installer variant whenever possible. The legacy 10.9+ Intel-only variant will not be provided for Python 3.10 and the universal2 variant will become the default download for 3.9.8. You may need to upgrade third-party components, like pip, to later versions. You may experience differences in behavior in IDLE and other Tk-based applications due to using the newer version of Tk. As always, if you encounter problems when using this installer variant, please check https://bugs.python.org for existing reports and for opening new issues. The next Python 3.9 maintenance release will be 3.9.8, currently scheduled for 2021-11-01. The Second Security-Only Release of Python 3.8 Get it here: https://www.python.org/downloads/release/python-3812/ Security content in this release contains four fixes. There are also four additional fixes for bugs that might have lead to denial-of-service attacks. Finally, while we?re not providing binary installers anymore, for those users who produce installers, we upgraded the OpenSSL version used to 1.1.1l. Take a look at the change log for details. According to the release calendar specified in PEP 569 , Python 3.8 is now in ?security fixes only? stage of its life cycle: 3.8 branch only accepts security fixes and releases of those are made irregularly in source-only form until October 2024. Python 3.8 isn?t receiving regular bug fixes anymore, and binary installers are no longer provided for it. Python 3.8.10 was the last full bugfix release of Python 3.8 with binary installers. Security releases of 3.7.12 and 3.6.15 Those aren?t ready just yet but are soon to follow. Similarly to 3.8, Python 3.7 and 3.6 are now in ?security fixes only? stage of their life cycle. Python 3.7 will be providing source archives until June 2023 while Python 3.6 ends its life in December 2021. We hope you enjoy the new releases Your friendly release team, Ned Deily @nad Steve Dower @steve.dower ?ukasz Langa @ambv -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: Message signed with OpenPGP URL: From wlfraed at ix.netcom.com Mon Aug 30 19:07:24 2021 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Mon, 30 Aug 2021 19:07:24 -0400 Subject: The sqlite3 timestamp conversion between unixepoch and localtime can't be done according to the timezone setting on the machine automatically. References: <715e310e-56e3-4c97-a454-770c709ea706n@googlegroups.com> Message-ID: On Sun, 29 Aug 2021 19:49:19 -0700 (PDT), "hongy... at gmail.com" declaimed the following: >On Ubuntu 20.04.2 LTS, I use the [recent2](https://github.com/dotslash/recent2/blob/master/recent2.py) to log and query my bash history, which uses a sqlite3 database to store the history information. The `datetime` of running a command is inserted in the sqlite3 database with [a `unixepoch` format](https://github.com/dotslash/recent2/blob/f1018aee228c710cc7d1b8b93bc0228791a54563/recent2.py#L45), and it will be converted into `localtime` accordingly when retrieved and displayed later. > As I read it, it is interpreting whatever value was provided as UNIXEPOCH when storing the value -- but stores it as an ISO date/time string! https://www.sqlite.org/lang_datefunc.html sqlite> select datetime(1092941466, 'unixepoch'); 2004-08-19 18:51:06 sqlite> sqlite> select datetime('now'); 2021-08-30 22:28:58 sqlite> I can't see anything in that code listing that explicitly manipulates the date/time when fetched for output. Nor do I see the connection specifying Python adapter usage: https://docs.python.org/3/library/sqlite3.html#default-adapters-and-converters so I'd expect the output to be in ISO UTC format; the native result of using SQLite3's datetime().. """ if not args.hide_time: cmd_time = row_dict["command_dt"] if args.time_first: print(f'{Term.YELLOW}{cmd_time}{Term.ENDC} {colored_cmd}') else: padded_cmd = pad(raw_text=row_dict['command'], print_text=colored_cmd) print(f'{padded_cmd} # rtime@ {Term.YELLOW}{cmd_time}{Term.ENDC}') """ >But I found that it did not perform the correct conversion according to the time zone setting on the machine, as shown below: >```shell >werner at X10DAi-00:~$ rm 222222222222222222 >rm: cannot remove '222222222222222222': No such file or directory >werner at X10DAi-00:~$ recent -fo -w . 2222222222222 >rm 222222222222222222 # rtime@ 2021-08-29 10:57:13 >werner at X10DAi-00:~$ date >Sun 29 Aug 2021 06:57:22 PM CST >``` Might have helped to mention you were in China... To me, CST is North America Central Standard Time (and I'd have expected this time of year to see CDT - Central Daylight Time)... That led me on a weird meaningless side track... What documentation do you have that says it will display the date/time in local timezone? (The README appears to be incorrect -- the utility logs unix epoch [UTC seconds since 1970] AS ISO UTC string). sqlite> select datetime(1092941466, 'unixepoch'); 2004-08-19 18:51:06 sqlite> select datetime(1092941466, 'unixepoch', 'localtime'); 2004-08-19 14:51:06 sqlite> sqlite> select datetime('now', 'localtime'); 2021-08-30 18:50:19 sqlite> select datetime('now'); 2021-08-30 22:50:32 sqlite> I'm in EDT (Eastern Daylight Time) -- so 4 hours behind UTC. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From wlfraed at ix.netcom.com Mon Aug 30 19:20:15 2021 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Mon, 30 Aug 2021 19:20:15 -0400 Subject: software installation problems References: Message-ID: <66pqigd2adfdc0r0ptf9veu3nno2uu4o8b@4ax.com> On Mon, 30 Aug 2021 10:37:26 -0500, randy darwin lozanovalle declaimed the following: >Good morning, when I run the Python program after installing the >latest version, I get this message (attached file), I have already >reinstalled the program several times and the same message keeps >appearing; What solution could you give me, thank you! No attachments on this forum -- if it can't be cut&paste TEXT you will have to put the image on some file server and provide a URL -- note that if said URL is some nasty numeric string from a shortener, many of us will NOT click on it -- the URL should be a clear string with the ending telling WHAT exactly is being accessed (.../screenimage.jpg for example). However, 99% of the time the matter is very simple... You are clicking on the INSTALLER file. Python is NOT a GUI IDE. Once you have installed it, hide that installer file somewhere -- on a USB flash drive say -- and delete it from where ever you downloaded it to. Python is a command line interpreter, one edits Python scripts using the editor of their choice (not a word processor), and runs it from the command shell by entering something like python myscript.py -=-=- C:\Users\Wulfraed>type Script1.py from pathlib import Path def listItems(basepath): print("Processing: %s" % basepath) items = list(basepath.iterdir()) files = [x for x in items if x.is_file()] dirs = [x for x in items if x.is_dir()] for f in files: print("\tFile: %s" % f) for d in dirs: listItems(d) if __name__ == "__main__": p = Path(".") listItems(p) C:\Users\Wulfraed>python3 script.py python3: can't open file 'script.py': [Errno 2] No such file or directory C:\Users\Wulfraed>python3 script1.py Processing: . File: .flexprop.config File: .gitconfig File: .kdiff3rc File: .python_history File: .RData File: .Rhistory File: 2015 Wards Geology Catalog.pdf File: aCalendar.HTML File: all_ddl.sql File: BBBser.py File: BBBser2.py File: BBBser3.py File: clang_ref_cache.db File: cp.txt File: D74.pdf File: default-loc.xml File: default.gpr File: demo.bexch File: demo.c File: demo.c.stderr File: demo.c.stdout File: demo.d File: demo.exe File: demo.o SNIP -=-=- Python is packaged by a number of providers, not just python.org (among other there are ActiveState, AnaConda, and now the Win10 M$ application store has a python installer). What is included with each package differs -- many may include a Tkinter script called IDLE as a basic IDE (I don't use it, and hated it the few times I had to start it at work; ActiveState Windows installs included PythonWin as an IDE -- but in the last few years ActiveState has required one to register with them before one can download their package). -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From alan.gauld at yahoo.co.uk Mon Aug 30 19:24:38 2021 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Tue, 31 Aug 2021 00:24:38 +0100 Subject: Python UI (was Re: urgent) In-Reply-To: References: Message-ID: On 29/08/2021 11:28, Hari wrote: > i was download ur python software but it is like boring user interface I agree it is a boring user interface. Just 3 chevrons: >>> You can change it a little if you want but ultimately its just an invitation to type commands. What kind of interface did you have in mind? If you want a GUI to develop code there are literally dozens of those. But ultimately programming is about typing text into an editor. > me like young student to learn ,can u have any updates? There are many tools to help you work with python. If you tell us what kind of things you want we can tell you where to find them (if they exist!) But the basic Python interpreter is primarily there to run your programs, it's hard to see how you can make that less boring without also making it very inefficient. And professional users would hate that! -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From PythonList at DancesWithMice.info Mon Aug 30 21:16:30 2021 From: PythonList at DancesWithMice.info (dn) Date: Tue, 31 Aug 2021 13:16:30 +1200 Subject: The sqlite3 timestamp conversion between unixepoch and localtime can't be done according to the timezone setting on the machine automatically. In-Reply-To: References: <715e310e-56e3-4c97-a454-770c709ea706n@googlegroups.com> Message-ID: <82b49bdc-36f3-2429-06cd-bd370ba3dfd7@DancesWithMice.info> On 31/08/2021 11.07, Dennis Lee Bieber wrote: > On Sun, 29 Aug 2021 19:49:19 -0700 (PDT), "hongy... at gmail.com" > declaimed the following: ... > Might have helped to mention you were in China... To me, CST is North > America Central Standard Time (and I'd have expected this time of year to > see CDT - Central Daylight Time)... That led me on a weird meaningless side > track... ... > I'm in EDT (Eastern Daylight Time) -- so 4 hours behind UTC. Which is correct? CST in China https://www.timeanddate.com/time/zones/cst-china CST in North America https://www.timeanddate.com/time/zones/cst and not to mention Cuba https://www.timeanddate.com/time/zones/ ?Time zones are often represented by alphabetic abbreviations such as "EST", "WST", and "CST", but these are not part of the international time and date standard ISO 8601 and their use as sole designator for a time zone is discouraged. Such designations can be ambiguous; for example, "CST" can mean China Standard Time (UTC+8), Cuba Standard Time (UTC?5), and (North American) Central Standard Time (UTC?6), and it is also a widely used variant of ACST (Australian Central Standard Time, UTC+9:30). Such designations predate both ISO 8601 and the internet era; in an earlier era, they were sufficiently unambiguous for many practical uses within a national context (for example, in railway timetables and business correspondence), but their ambiguity explains their deprecation in the internet era, when communications more often cannot rely on implicit geographic context to supply part of the meaning.? https://en.wikipedia.org/wiki/List_of_time_zone_abbreviations This is why ISO8601 uses the ?HH:MM numeric suffix to designate a local time-zone (cf UTC - or as we used to say in the UK, "GMT", and in the military, "Zulu"). Most of us know about ISO8601 formatting, even if we think of it as something like the way Unix-time is expressed, rather than it being an international standard. Few are aware that "8601" has been extended to cover less-obvious dates, times, and durations. For example, do you know that today is (said to be) "the last day of winter"? Assuming you, dear reader, are in the northern hemisphere, indeed are living in a temperate zone (cf the tropics or closer to one of the poles), you reacted by exclaiming "what!?". Thus, one of the 8601 "extensions" deals with the idea that climatic seasons have meaning to locations within a narrow range of latitudes, and that they are six-month inverses between the earth's hemispheres. So, you couldn't understand/didn't believe me - yet I am completely correct. (as always - cough, splutter, snort...) Welcome to the last day of (what may be) your summer! These things can be tricky... -- Regards, =dn From arj.python at gmail.com Tue Aug 31 02:53:24 2021 From: arj.python at gmail.com (Abdur-Rahmaan Janhangeer) Date: Tue, 31 Aug 2021 10:53:24 +0400 Subject: src layout for projects seems not so popular Message-ID: Greetings list, Just an observation. Out of Github's trending repos for Python for today, I could find only 2 repos using the src layout. Matplotlib and another one. https://github.com/trending/python?since=daily Kind Regards, Abdur-Rahmaan Janhangeer about | blog github Mauritius From arj.python at gmail.com Tue Aug 31 03:09:36 2021 From: arj.python at gmail.com (Abdur-Rahmaan Janhangeer) Date: Tue, 31 Aug 2021 11:09:36 +0400 Subject: src layout for projects seems not so popular In-Reply-To: References: Message-ID: Also a takeaway from my package experience is that even though __init__.py is not needed for module import, it's still needed for packaging (py3.8). Find won't find the module else. Kind Regards, Abdur-Rahmaan Janhangeer about | blog github Mauritius From python at mrabarnett.plus.com Tue Aug 31 06:53:55 2021 From: python at mrabarnett.plus.com (MRAB) Date: Tue, 31 Aug 2021 11:53:55 +0100 Subject: The sqlite3 timestamp conversion between unixepoch and localtime can't be done according to the timezone setting on the machine automatically. In-Reply-To: <82b49bdc-36f3-2429-06cd-bd370ba3dfd7@DancesWithMice.info> References: <715e310e-56e3-4c97-a454-770c709ea706n@googlegroups.com> <82b49bdc-36f3-2429-06cd-bd370ba3dfd7@DancesWithMice.info> Message-ID: On 2021-08-31 02:16, dn via Python-list wrote: > On 31/08/2021 11.07, Dennis Lee Bieber wrote: >> On Sun, 29 Aug 2021 19:49:19 -0700 (PDT), "hongy... at gmail.com" >> declaimed the following: > ... > >> Might have helped to mention you were in China... To me, CST is North >> America Central Standard Time (and I'd have expected this time of year to >> see CDT - Central Daylight Time)... That led me on a weird meaningless side >> track... > ... > >> I'm in EDT (Eastern Daylight Time) -- so 4 hours behind UTC. > > > Which is correct? > > CST in China > https://www.timeanddate.com/time/zones/cst-china > > CST in North America > https://www.timeanddate.com/time/zones/cst > > and not to mention Cuba > https://www.timeanddate.com/time/zones/ > [snip] What annoys me is when someone starts that a webinar will start at, say, xx ET. I have to know which country that person is in and whether daylight savings is currently in effect (EST or EDT?) so that I can convert to my local time. It's so much easier to use UTC. I know what timezone I'm in and whether daylight savings is currently in effect here, so I know the local offset from UTC. From rosuav at gmail.com Tue Aug 31 08:45:44 2021 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 31 Aug 2021 22:45:44 +1000 Subject: The sqlite3 timestamp conversion between unixepoch and localtime can't be done according to the timezone setting on the machine automatically. In-Reply-To: References: <715e310e-56e3-4c97-a454-770c709ea706n@googlegroups.com> <82b49bdc-36f3-2429-06cd-bd370ba3dfd7@DancesWithMice.info> Message-ID: On Tue, Aug 31, 2021 at 8:55 PM MRAB wrote: > > On 2021-08-31 02:16, dn via Python-list wrote: > > On 31/08/2021 11.07, Dennis Lee Bieber wrote: > >> On Sun, 29 Aug 2021 19:49:19 -0700 (PDT), "hongy... at gmail.com" > >> declaimed the following: > > ... > > > >> Might have helped to mention you were in China... To me, CST is North > >> America Central Standard Time (and I'd have expected this time of year to > >> see CDT - Central Daylight Time)... That led me on a weird meaningless side > >> track... > > ... > > > >> I'm in EDT (Eastern Daylight Time) -- so 4 hours behind UTC. > > > > > > Which is correct? > > > > CST in China > > https://www.timeanddate.com/time/zones/cst-china > > > > CST in North America > > https://www.timeanddate.com/time/zones/cst > > > > and not to mention Cuba > > https://www.timeanddate.com/time/zones/ > > > [snip] > What annoys me is when someone starts that a webinar will start at, say, > xx ET. I have to know which country that person is in and whether > daylight savings is currently in effect (EST or EDT?) so that I can > convert to my local time. If someone says "ET", then I would assume they mean America/New_York - it seems that only in the US do people so utterly assume that everyone else is in the same country. In Europe, I hear people say "CEST" and such (though I still prefer "Europe/Prague" or whatever country they're in), so the only issue there is that they don't always say "CEDT" when it's daylight time. > It's so much easier to use UTC. > > I know what timezone I'm in and whether daylight savings is currently in > effect here, so I know the local offset from UTC. Yeah. I do recommend making good use of the IANA tzinfo database though (especially since Python 3.9 made that a bit easier to access), as it's usually easier to get people to tell you what city/state they're in, rather than whether daylight time will be active or not. (It might take a little bit of translation to figure out that, for instance, New Brunswick CA is America/Halifax, but that's not too hard usually.) Letting tzinfo do all the work means you don't have to fret about anyone's daylight saving transition dates, or whether they've decided to change their clocks by half an hour to be different from Japan's clocks, or to have DST not applicable during Ramadan, or to have double DST, or double-negative DST. And yes, those are all real, because you can't make up anything as insane as actual clock politics. (I find the Ireland situation particularly amusing. Northern Ireland, being part of the UK, operates on London time, with clocks advancing one hour for summer. The Republic of Ireland, on the other hand, has a standard time which is one hour later than Greenwich's, but then they subtract an hour during winter, returning to standard time in summer. So when the rest of Europe adds an hour, Ireland stops subtracting one. Clocks in Belfast and Dublin always show the same times.) ChrisA From cspealma at redhat.com Tue Aug 31 09:01:33 2021 From: cspealma at redhat.com (Calvin Spealman) Date: Tue, 31 Aug 2021 09:01:33 -0400 Subject: PEP Idea: Real private attribute In-Reply-To: References: Message-ID: The right way for those decorators to hold some private information, imho, isn't to put anything on the decorated object at all, but to use a weak-ref dictionary using the target object as a key. On Sat, Aug 28, 2021 at 5:42 PM Mehrzad Saremi wrote: > Python currently uses name mangling for double-underscore attributes. Name > mangling is not an ideal method to avoid name conflicting. There are > various normal programming patterns that can simply cause name conflicting > in double-underscore members. A typical example is when a class is > re-decorated using the same decorator. The decorator can not take > double-underscore members without name conflicts. For example: > > ``` > @custom_decorator("a") > @custom_decorator("b") > class C: > pass > ``` > > The `@custom_decorator` wrapper may need to hold private members, but > Python's current name conflict resolution does not provide any solution and > the decorator cannot hold private members without applying tricky > programming methods. > > Another example is when a class inherits from a base class of the same > name. > > ``` > class View: > """A class representing a view of an object; similar to > numpy.ndarray.view""" > pass > > class Object: > class View(View): > """A view class costumized for objects of type Object""" > pass > ``` > > Again, in this example, class `Object.View` can't take double-underscore > names without conflicting with `View`'s. > > My idea is to introduce real private members (by which I do not mean to be > inaccessible from outside the class, but to be guaranteed not to conflict > with other private members of the same object). These private members are > started with triple underscores and are stored in a separate dictionary > named `__privs__`. Unlike `__dict__` that takes 'str' keys, `__privs__` > will be a double layer dictionary that takes 'type' keys in the first > level, and 'str' keys in the second level. > > For example, assume that the user runs the following code: > ``` > class C: > def __init__(self, value): > self.___member = value > > c = C("my value") > ``` > > On the last line, Python's attribute setter creates a new entry in the > dictionary with key `C`, adds the value "my value" to a new entry with the > key 'member'. > > The user can then retrieve `c.___member` by invoking the `__privs__` > dictionary: > > ``` > print(c.__privs__[C]['member']) # prints 'my value' > ``` > > Note that, unlike class names, class objects are unique and there will not > be any conflicts. Python classes are hashable and can be dictionary keys. > Personally, I do not see any disadvantage of using __privs__ over name > mangling/double-underscores. While name mangling does not truly guarantee > conflict resolution, __privs__ does. > > Please discuss the idea, let me know what you think about it, whether there > are possible disadvantages, and if you think it will be approved as a PEP. > > Thanks, > Mehrzad Saremi > > AI M.Sc. grad. from AUT > -- > https://mail.python.org/mailman/listinfo/python-list > > -- CALVIN SPEALMAN SENIOR QUALITY ENGINEER calvin.spealman at redhat.com M: +1.336.210.5107 [image: https://red.ht/sig] TRIED. TESTED. TRUSTED. From george at fischhof.hu Tue Aug 31 10:35:46 2021 From: george at fischhof.hu (George Fischhof) Date: Tue, 31 Aug 2021 16:35:46 +0200 Subject: Making command-line args available to deeply-nested functions In-Reply-To: References: <87czq8tpay.fsf@hornfels.zedat.fu-berlin.de> <230149ee-f6ed-4e2f-8ac3-c12388ca45acn@googlegroups.com> <878s0wtljf.fsf@hornfels.zedat.fu-berlin.de> <87sfz0y0gx.fsf@hornfels.zedat.fu-berlin.de> <87sfyw7cvn.fsf@hornfels.zedat.fu-berlin.de> Message-ID: George Fischhof ezt ?rta (id?pont: 2021. aug. 29., V, 21:27): > > > Loris Bennett ezt ?rta (id?pont: 2021. aug. > 26., Cs, 16:02): > >> George Fischhof writes: >> >> [snip (79 lines)] >> >> >> > Hi, >> >> > >> >> > Also you can give a try to click and / or typer packages. >> >> > Putting args into environment variables can be a solution too >> >> > All of these depends on several things: personal preferences, >> colleagues >> >> / >> >> > firm standards, the program, readability, variable accessibility (IDE >> >> > support, auto completition) (env vars not supported by IDEs as they >> are >> >> not >> >> > part of code) >> >> >> >> Thanks for the pointers, although I have only just got my head around >> >> argparse/configargparse, so click is something I might have a look at >> >> for future project. >> >> >> >> However, the question of how to parse the arguments is somewhat >> separate >> >> from that of how to pass (or not pass) the arguments around within a >> >> program. >> >> [snip (16 lines)] >> > >> > Hi, >> > I thought not just parsing, but the usage method: you add a decorator to >> > the function where you want to use the parameters. This way you do not >> have >> > to pass the value through the calling hierarchy. >> > >> > Note: typer is a newer package, it contains click and leverages command >> > line parsing even more. >> >> Do you have an example of how this is done? From a cursory reading of >> the documentation, it didn't seem obvious to me how to do this, but then >> I don't have much understanding of how decorators work. >> >> Cheers, >> >> Loris >> >> >> -- >> This signature is currently under construction. >> -- >> https://mail.python.org/mailman/listinfo/python-list > > > Hi, > > will create a sample code on Monday - Tuesday > > BR, > George > Hi, here is the program ;-) (see below) typer does not uses decorators, to solve this problem they advice to use click's decorators, mixing typer and click. Practically I prefer not to mix them, also the parts for easiest way to do this just available in latest click, which is not supported in typer. So I created all the stuff in click, 8.x should be used BR, George import click # read command line parameters @click.command() @click.option('--level_1', help='Level 1') @click.option('--level_2', help='Level 2') def main(level_1, level_2): # put command line parameters into global context ctx = click.get_current_context() ctx.meta['level_1'] = level_1 ctx.meta['level_2'] = level_2 level_1_function() # pass / inject level_1 parameter to this function @click.decorators.pass_meta_key('level_1') def level_1_function(level_1): print(f'level 1 variable: {level_1}') level_2_function() # pass / inject level_2 parameter to this function @click.decorators.pass_meta_key('level_2') def level_2_function(level_2): print(f'level 2 variable: {level_2}') if __name__ == "__main__": main() From hongyi.zhao at gmail.com Tue Aug 31 01:10:33 2021 From: hongyi.zhao at gmail.com (hongy...@gmail.com) Date: Mon, 30 Aug 2021 22:10:33 -0700 (PDT) Subject: The sqlite3 timestamp conversion between unixepoch and localtime can't be done according to the timezone setting on the machine automatically. In-Reply-To: References: <715e310e-56e3-4c97-a454-770c709ea706n@googlegroups.com> Message-ID: On Tuesday, August 31, 2021 at 7:55:51 AM UTC+8, Dennis Lee Bieber wrote: > On Sun, 29 Aug 2021 19:49:19 -0700 (PDT), "hongy... at gmail.com" > declaimed the following: > >On Ubuntu 20.04.2 LTS, I use the [recent2](https://github.com/dotslash/recent2/blob/master/recent2.py) to log and query my bash history, which uses a sqlite3 database to store the history information. The `datetime` of running a command is inserted in the sqlite3 database with [a `unixepoch` format](https://github.com/dotslash/recent2/blob/f1018aee228c710cc7d1b8b93bc0228791a54563/recent2.py#L45), and it will be converted into `localtime` accordingly when retrieved and displayed later. > > > As I read it, it is interpreting whatever value was provided as > UNIXEPOCH when storing the value -- but stores it as an ISO date/time > string! https://www.sqlite.org/lang_datefunc.html > > sqlite> select datetime(1092941466, 'unixepoch'); > 2004-08-19 18:51:06 > sqlite> > sqlite> select datetime('now'); > 2021-08-30 22:28:58 > sqlite> > > I can't see anything in that code listing that explicitly manipulates > the date/time when fetched for output. Nor do I see the connection > specifying Python adapter usage: > https://docs.python.org/3/library/sqlite3.html#default-adapters-and-converters > so I'd expect the output to be in ISO UTC format; the native result of > using SQLite3's datetime().. > > """ > if not args.hide_time: > cmd_time = row_dict["command_dt"] Thank you very much. Based on your above comments and the discussion on , I fixed this problem by the following method: # Install and import some necessary packages: from datetime import datetime # pip install python-dateutil from dateutil import tz Then use the following codes to do the trick: from_zone = tz.tzutc() to_zone = tz.tzlocal() cmd_time = row_dict["command_dt"] cmd_time = datetime.strptime(cmd_time, '%Y-%m-%d %H:%M:%S').replace(tzinfo=from_zone).astimezone(to_zone).strftime("%Y-%m-%d %H:%M:%S") Best, Hongyi > if args.time_first: > print(f'{Term.YELLOW}{cmd_time}{Term.ENDC} > {colored_cmd}') > else: > padded_cmd = pad(raw_text=row_dict['command'], > print_text=colored_cmd) > print(f'{padded_cmd} # rtime@ > {Term.YELLOW}{cmd_time}{Term.ENDC}') > """ > >But I found that it did not perform the correct conversion according to the time zone setting on the machine, as shown below: > >```shell > >werner at X10DAi-00:~$ rm 222222222222222222 > >rm: cannot remove '222222222222222222': No such file or directory > >werner at X10DAi-00:~$ recent -fo -w . 2222222222222 > >rm 222222222222222222 # rtime@ 2021-08-29 10:57:13 > >werner at X10DAi-00:~$ date > >Sun 29 Aug 2021 06:57:22 PM CST > >``` > Might have helped to mention you were in China... To me, CST is North > America Central Standard Time (and I'd have expected this time of year to > see CDT - Central Daylight Time)... That led me on a weird meaningless side > track... > > What documentation do you have that says it will display the date/time > in local timezone? (The README appears to be incorrect -- the utility logs > unix epoch [UTC seconds since 1970] AS ISO UTC string). > > sqlite> select datetime(1092941466, 'unixepoch'); > 2004-08-19 18:51:06 > sqlite> select datetime(1092941466, 'unixepoch', 'localtime'); > 2004-08-19 14:51:06 > sqlite> > sqlite> select datetime('now', 'localtime'); > 2021-08-30 18:50:19 > sqlite> select datetime('now'); > 2021-08-30 22:50:32 > sqlite> > > I'm in EDT (Eastern Daylight Time) -- so 4 hours behind UTC. > > > -- > Wulfraed Dennis Lee Bieber AF6VN > wlf... at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From nospam at please.ty Tue Aug 31 03:05:36 2021 From: nospam at please.ty (jak) Date: Tue, 31 Aug 2021 09:05:36 +0200 Subject: urgent References: <612d803b$0$27423$426a74cc@news.free.fr> Message-ID: Il 31/08/2021 03:05, Python ha scritto: > Hari wrote: >> i was download ur python software but it is like boring user interface >> for >> me like young student to learn ,can u have any updates? > > God, let me die please... > > > Oh no, please don't speak in that way ... evidently now that python has reached its tenth version its prompt is a little boring. It may need to be replaced. You could open a competition notice to vote on the new prompt. I would vote for: :^P> rofl From simonppears at googlemail.com Tue Aug 31 06:59:52 2021 From: simonppears at googlemail.com (dcs3spp) Date: Tue, 31 Aug 2021 03:59:52 -0700 (PDT) Subject: Struggling to understand timedelta rpesentation when applying an offset for an hour earlier - why is days = -1? Message-ID: Hi, I wonder if anyone can help.... I am struggling to understand the representation of timedelta when used in conjunction with astimezone. Given the code below, in a python interactive interpreter, I am trying to calculate a resultant datetime an hour earlier from a UTC datetime.... ```bash >>> dt = datetime(2021, 8, 22, 23, 59, 31, tzinfo=timezone.utc) >>> hour_before=dt.astimezone(timezone(-timedelta(seconds=3600))) >>> hour_before datetime.datetime(2021, 8, 22, 22, 59, 31, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=82800))) ``` I cannot understand why the resultant datetime.timedelta is days=-1, seconds=82800 (23 hours) . Why is it not an hour earlier as seconds=-3600? Why is days = -1 when the resultant calculated date is the same, year, day, month?? From alan.gauld at yahoo.co.uk Tue Aug 31 09:11:32 2021 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Tue, 31 Aug 2021 14:11:32 +0100 Subject: The sqlite3 timestamp conversion between unixepoch and localtime can't be done according to the timezone setting on the machine automatically. In-Reply-To: References: <715e310e-56e3-4c97-a454-770c709ea706n@googlegroups.com> <82b49bdc-36f3-2429-06cd-bd370ba3dfd7@DancesWithMice.info> Message-ID: On 31/08/2021 13:45, Chris Angelico wrote: > (I find the Ireland situation particularly amusing. Time zones and daylight saving arrangements in particular are a nightmare at the micro level. I once worked on a large customer support application which required all dates/times to be viewable in UTC plus any of: - The local support centre's time (eg. Tokyo, Japan) - The customer organization's local time(eg. Seoul, Korea) - The local site time (some remote island in the pacific...) The big problem was the last one since some small countries have local arrangements for timezones that don't conform to the official ones. One pacific island had dual "patrons" and to avoid offending either they adopted a non-standard "timezone" half-way between the two patron's zones! In another case we had the principality of Andorra deciding to put off switching to DST for an extra week because it would make the snow melt faster and spoil the skiing! This was decided by the council on the Friday before it was due to happen and announced on the local radio... I got more grey hairs on that project than any other. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From hongyi.zhao at gmail.com Tue Aug 31 09:12:42 2021 From: hongyi.zhao at gmail.com (hongy...@gmail.com) Date: Tue, 31 Aug 2021 06:12:42 -0700 (PDT) Subject: Create a real-time interactive TUI using Python. Message-ID: I want to know whether python can be used to create real-time interactive TUI, as hstr [1] does. [1] https://github.com/dvorka/hstr Regards, HY From loris.bennett at fu-berlin.de Tue Aug 31 09:25:42 2021 From: loris.bennett at fu-berlin.de (Loris Bennett) Date: Tue, 31 Aug 2021 15:25:42 +0200 Subject: Trouble propagating logging configuration Message-ID: <87eea9zqy1.fsf@hornfels.zedat.fu-berlin.de> Hi, I am having difficulty getting the my logging configuration passed on to imported modules. My initial structure was as follows: $ tree blorp/ blorp/ |-- blorp | |-- __init__.py | |-- bar.py | |-- foo.py | `-- main.py `-- pyproject.toml whereby the logging configuration is done in main.py. After thinking about it, I decided maybe the inheritance wasn't working because main.py is in the same directory as the other files. So I changed the structure to $ tree blorp/ blorp/ |-- blorp | |-- __init__.py | |-- bar.py | `-- foo.py |-- main.py `-- pyproject.toml but the logging configuration still is not propagated. Can anyone at least confirm that moving main.py to the directory above the other files is the correct thing to do and thus the problem is being caused by something else? Cheers, Loris -- This signature is currently under construction. From loris.bennett at fu-berlin.de Tue Aug 31 09:38:18 2021 From: loris.bennett at fu-berlin.de (Loris Bennett) Date: Tue, 31 Aug 2021 15:38:18 +0200 Subject: Trouble propagating logging configuration References: <87eea9zqy1.fsf@hornfels.zedat.fu-berlin.de> Message-ID: <87a6kxzqd1.fsf@hornfels.zedat.fu-berlin.de> "Loris Bennett" writes: > Hi, > > I am having difficulty getting the my logging configuration passed on > to imported modules. > > My initial structure was as follows: > > $ tree blorp/ > blorp/ > |-- blorp > | |-- __init__.py > | |-- bar.py > | |-- foo.py > | `-- main.py > `-- pyproject.toml > > whereby the logging configuration is done in main.py. > > After thinking about it, I decided maybe the inheritance wasn't working > because main.py is in the same directory as the other files. So I > changed the structure to > > $ tree blorp/ > blorp/ > |-- blorp > | |-- __init__.py > | |-- bar.py > | `-- foo.py > |-- main.py > `-- pyproject.toml > > but the logging configuration still is not propagated. > > Can anyone at least confirm that moving main.py to the directory above > the other files is the correct thing to do and thus the problem is being > caused by something else? I should mention that I am using poetry and thus the program is called via an entry in the pyproject.toml file such as [tool.poetry.scripts] blorp_out = "main:blorp_out" I have a suspicion that this way of calling the program somehow interferes with the inheritance mechanism used by logging. Cheers, Loris -- This signature is currently under construction. From hariharan1995.senthil at gmail.com Tue Aug 31 01:44:40 2021 From: hariharan1995.senthil at gmail.com (Hari) Date: Tue, 31 Aug 2021 11:14:40 +0530 Subject: urgent In-Reply-To: References: Message-ID: Yes, I can. Why do you want python? option: ? What task do you want to solve with python? option: ? Why python? option: ? Why not any other language? option: ? On Tue, Aug 31, 2021 at 3:08 AM Igor Korot wrote: > Hi, > > On Mon, Aug 30, 2021 at 4:34 PM Hari > wrote: > > > > i was download ur python software but it is like boring user interface > for > > me like young student to learn ,can u have any updates? > > Can you elaborate a little: > Why do you want python? > What task do you want to solve with python? > Why python? Why not any other language? > > Thank you. > > > -- > > https://mail.python.org/mailman/listinfo/python-list > From ikorot01 at gmail.com Tue Aug 31 12:20:49 2021 From: ikorot01 at gmail.com (Igor Korot) Date: Tue, 31 Aug 2021 11:20:49 -0500 Subject: urgent In-Reply-To: References: Message-ID: Hi, On Tue, Aug 31, 2021 at 12:44 AM Hari wrote: > > Yes, I can. Why do you want python? > option: ? What do you mean - "option". I am actually asking you why you want python? > What task do you want to solve with python? > option: ? See above. > Why python? > option: ? > Why not any other language? > option: ? Those 2 depend on the task at hand. Thank you. > > > On Tue, Aug 31, 2021 at 3:08 AM Igor Korot wrote: >> >> Hi, >> >> On Mon, Aug 30, 2021 at 4:34 PM Hari wrote: >> > >> > i was download ur python software but it is like boring user interface for >> > me like young student to learn ,can u have any updates? >> >> Can you elaborate a little: >> Why do you want python? >> What task do you want to solve with python? >> Why python? Why not any other language? >> >> Thank you. >> >> > -- >> > https://mail.python.org/mailman/listinfo/python-list From rosuav at gmail.com Tue Aug 31 12:49:17 2021 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 1 Sep 2021 02:49:17 +1000 Subject: Create a real-time interactive TUI using Python. In-Reply-To: References: Message-ID: On Wed, Sep 1, 2021 at 1:59 AM hongy... at gmail.com wrote: > > I want to know whether python can be used to create real-time interactive TUI, as hstr [1] does. > > [1] https://github.com/dvorka/hstr > Yes. ChrisA From mehrzad.1024 at gmail.com Tue Aug 31 13:18:37 2021 From: mehrzad.1024 at gmail.com (Mehrzad Saremi) Date: Tue, 31 Aug 2021 21:48:37 +0430 Subject: PEP Idea: Real private attribute In-Reply-To: References: Message-ID: Calvin, even if the language offered truly private members? On Tue, 31 Aug 2021 at 17:31, Calvin Spealman wrote: > The right way for those decorators to hold some private information, imho, > isn't to put anything on the decorated object at all, but to use a weak-ref > dictionary using the target object as a key. > > On Sat, Aug 28, 2021 at 5:42 PM Mehrzad Saremi > wrote: > >> Python currently uses name mangling for double-underscore attributes. Name >> mangling is not an ideal method to avoid name conflicting. There are >> various normal programming patterns that can simply cause name conflicting >> in double-underscore members. A typical example is when a class is >> re-decorated using the same decorator. The decorator can not take >> double-underscore members without name conflicts. For example: >> >> ``` >> @custom_decorator("a") >> @custom_decorator("b") >> class C: >> pass >> ``` >> >> The `@custom_decorator` wrapper may need to hold private members, but >> Python's current name conflict resolution does not provide any solution >> and >> the decorator cannot hold private members without applying tricky >> programming methods. >> >> Another example is when a class inherits from a base class of the same >> name. >> >> ``` >> class View: >> """A class representing a view of an object; similar to >> numpy.ndarray.view""" >> pass >> >> class Object: >> class View(View): >> """A view class costumized for objects of type Object""" >> pass >> ``` >> >> Again, in this example, class `Object.View` can't take double-underscore >> names without conflicting with `View`'s. >> >> My idea is to introduce real private members (by which I do not mean to be >> inaccessible from outside the class, but to be guaranteed not to conflict >> with other private members of the same object). These private members are >> started with triple underscores and are stored in a separate dictionary >> named `__privs__`. Unlike `__dict__` that takes 'str' keys, `__privs__` >> will be a double layer dictionary that takes 'type' keys in the first >> level, and 'str' keys in the second level. >> >> For example, assume that the user runs the following code: >> ``` >> class C: >> def __init__(self, value): >> self.___member = value >> >> c = C("my value") >> ``` >> >> On the last line, Python's attribute setter creates a new entry in the >> dictionary with key `C`, adds the value "my value" to a new entry with the >> key 'member'. >> >> The user can then retrieve `c.___member` by invoking the `__privs__` >> dictionary: >> >> ``` >> print(c.__privs__[C]['member']) # prints 'my value' >> ``` >> >> Note that, unlike class names, class objects are unique and there will not >> be any conflicts. Python classes are hashable and can be dictionary keys. >> Personally, I do not see any disadvantage of using __privs__ over name >> mangling/double-underscores. While name mangling does not truly guarantee >> conflict resolution, __privs__ does. >> >> Please discuss the idea, let me know what you think about it, whether >> there >> are possible disadvantages, and if you think it will be approved as a PEP. >> >> Thanks, >> Mehrzad Saremi >> >> AI M.Sc. grad. from AUT >> -- >> https://mail.python.org/mailman/listinfo/python-list >> >> > > -- > > CALVIN SPEALMAN > > SENIOR QUALITY ENGINEER > > calvin.spealman at redhat.com M: +1.336.210.5107 > [image: https://red.ht/sig] > TRIED. TESTED. TRUSTED. > From dieter at handshake.de Tue Aug 31 13:01:53 2021 From: dieter at handshake.de (Dieter Maurer) Date: Tue, 31 Aug 2021 19:01:53 +0200 Subject: Trouble propagating logging configuration In-Reply-To: <87eea9zqy1.fsf@hornfels.zedat.fu-berlin.de> References: <87eea9zqy1.fsf@hornfels.zedat.fu-berlin.de> Message-ID: <24878.24705.612533.264970@ixdm.fritz.box> Loris Bennett wrote at 2021-8-31 15:25 +0200: >I am having difficulty getting the my logging configuration passed on >to imported modules. > >My initial structure was as follows: > > $ tree blorp/ > blorp/ > |-- blorp > | |-- __init__.py > | |-- bar.py > | |-- foo.py > | `-- main.py > `-- pyproject.toml > >whereby the logging configuration is done in main.py. > >After thinking about it, I decided maybe the inheritance wasn't working >because main.py is in the same directory as the other files. Should you speak about Python's `logging` module, then the "inheritance" does not depend on the source layout. Instead, it is based on the hierarchy of dotted names. It is completely up to you which dotted names you are using in your `getLogger` calls. Furthermore, the place of the configuration (and where in the code it is activated) is completely irrelevant for the "inheritance". For details, read the Python documentation for the `logging` module. From pbryan at anode.ca Tue Aug 31 14:57:05 2021 From: pbryan at anode.ca (Paul Bryan) Date: Tue, 31 Aug 2021 11:57:05 -0700 Subject: src layout for projects seems not so popular In-Reply-To: References: Message-ID: An interesting thread in PyPA (with links to other threads) discussing src layout: https://github.com/pypa/packaging.python.org/issues/320 On Tue, 2021-08-31 at 10:53 +0400, Abdur-Rahmaan Janhangeer wrote: > Greetings list, > > Just an observation. Out of Github's trending repos for > Python for today, I could find only 2 repos using the src layout. > Matplotlib and another one. > https://github.com/trending/python?since=daily > > Kind Regards, > > Abdur-Rahmaan Janhangeer > about | blog > > github > Mauritius From rosuav at gmail.com Tue Aug 31 15:39:32 2021 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 1 Sep 2021 05:39:32 +1000 Subject: Struggling to understand timedelta rpesentation when applying an offset for an hour earlier - why is days = -1? In-Reply-To: References: Message-ID: On Wed, Sep 1, 2021 at 1:55 AM dcs3spp via Python-list wrote: > > Hi, > > I wonder if anyone can help.... > > I am struggling to understand the representation of timedelta when used in conjunction with astimezone. > > Given the code below, in a python interactive interpreter, I am trying to calculate a resultant datetime an hour earlier from a UTC datetime.... > > ```bash > >>> dt = datetime(2021, 8, 22, 23, 59, 31, tzinfo=timezone.utc) > >>> hour_before=dt.astimezone(timezone(-timedelta(seconds=3600))) > >>> hour_before > datetime.datetime(2021, 8, 22, 22, 59, 31, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=82800))) > ``` > > I cannot understand why the resultant datetime.timedelta is days=-1, seconds=82800 (23 hours) . > > Why is it not an hour earlier as seconds=-3600? Why is days = -1 when the resultant calculated date is the same, year, day, month?? It's consistent with modulo arithmetic: >>> x = -3600 >>> x // 86400 -1 >>> x % 86400 82800 >>> help(datetime.timedelta) ... | ---------------------------------------------------------------------- | Data descriptors defined here: | | days | Number of days. | | microseconds | Number of microseconds (>= 0 and less than 1 second). | | seconds | Number of seconds (>= 0 and less than 1 day). | | ---------------------------------------------------------------------- The sub-day portions are guaranteed to be zero or above, meaning that a small negative offset is described as "a day ago, plus 23 hours" rather than "an hour ago". It's the exact same thing, though. If you would prefer to see ALL components negative, just negate the timedelta and then negate each component; that will give you an equivalent timedelta. >>> datetime.timedelta(seconds=-3600) datetime.timedelta(days=-1, seconds=82800) >>> -datetime.timedelta(seconds=-3600) datetime.timedelta(seconds=3600) >>> datetime.timedelta(seconds=-3600-86400) datetime.timedelta(days=-2, seconds=82800) >>> -datetime.timedelta(seconds=-3600-86400) datetime.timedelta(days=1, seconds=3600) Hope that explains it! ChrisA From PythonList at DancesWithMice.info Tue Aug 31 16:36:55 2021 From: PythonList at DancesWithMice.info (dn) Date: Wed, 1 Sep 2021 08:36:55 +1200 Subject: The sqlite3 timestamp conversion between unixepoch and localtime can't be done according to the timezone setting on the machine automatically. In-Reply-To: References: <715e310e-56e3-4c97-a454-770c709ea706n@googlegroups.com> <82b49bdc-36f3-2429-06cd-bd370ba3dfd7@DancesWithMice.info> Message-ID: <5453b2a9-1a77-1aa1-e18e-f08904aaeabb@DancesWithMice.info> On 01/09/2021 00.45, Chris Angelico wrote: > On Tue, Aug 31, 2021 at 8:55 PM MRAB wrote: >> On 2021-08-31 02:16, dn via Python-list wrote: >>> On 31/08/2021 11.07, Dennis Lee Bieber wrote: >>>> On Sun, 29 Aug 2021 19:49:19 -0700 (PDT), "hongy... at gmail.com" >>>> declaimed the following: >>> ... >>> >>>> Might have helped to mention you were in China... To me, CST is North >>>> America Central Standard Time (and I'd have expected this time of year to >>>> see CDT - Central Daylight Time)... That led me on a weird meaningless side >>>> track... >>> ... >>> >>>> I'm in EDT (Eastern Daylight Time) -- so 4 hours behind UTC. >>> >>> >> What annoys me is when someone starts that a webinar will start at, say, >> xx ET. I have to know which country that person is in and whether >> daylight savings is currently in effect (EST or EDT?) so that I can >> convert to my local time. > > If someone says "ET", then I would assume they mean America/New_York - > it seems that only in the US do people so utterly assume that everyone > else is in the same country. In Europe, I hear people say "CEST" and > such (though I still prefer "Europe/Prague" or whatever country > they're in), so the only issue there is that they don't always say > "CEDT" when it's daylight time. We tackle the inter-related subjects of "localisation" and "internationalisation" in our (non-Python) training courses. The 'problem' with a local-time, eg "0900 ET" (as above), is that it is local. It is really only intended to communicate locally. The definitions of "local" and 'local understanding' do vary. For example, Australia stretches over multiple time-zones and thus people in Melbourne are familiar with the idea of adjusting a Sydney-time to their local clock. Similarly, US-based folk. However, many other localities don't have such concerns and thus don't think that way! At the level of "inter-personal communication", should one say (only) what is in your head, or perform the 'translation' as a politeness to your reader? In @Chris' example, 'the reader' could be anywhere in the world. So, it would be difficult, and lengthy, to provide for all - but should you write such an invitation 'for all' ("Hi Everyone"), or should it be addressed to the individual reader ("Dear Colleague")? After years (decades!) of being woken in the early-hours of the morning by (time-zone-ignorant) colleagues, my recommendation is to use both! If the invitation is mine, typically I will write ("transmit") my local time, because that is how I'm thinking as I type. On a second-pass/editing the text, I will be considering how the reader will "receive" the information. If we're talking about a staff-meeting, it may be possible to list the reader's time/date. In the case of an webinar hoping to attract international participation, the recommendation is to add a UTC-equivalent. (ideas developed, below) >> It's so much easier to use UTC. >> >> I know what timezone I'm in and whether daylight savings is currently in >> effect here, so I know the local offset from UTC. Exactly! The very purpose of having an "international" standard. Also, the very reason why Python has two groups of time-and-date functions - so that one may work in local-time, or international-time/UTC. Please note, the adjustments described (offsets) are *numeric*. Accordingly, being told that one of our members resides 'at' UTC-4, and knowing that I am currently at UTC+12, we can figure-out a 16-hour 'time-difference'. NB in reality, having too few fingers, I would go 'the other way' (ie 24 - 16 ) and work with the idea that our colleague's clock is eight-hours 'ahead' of mine (so, as I've recently 'passed' 0800, that would make it ~1600/4pm for him - remembering that I am already 'in' Wednesday, whereas Americans are still struggling to catch-up by finishing Tuesday) > Yeah. I do recommend making good use of the IANA tzinfo database > though (especially since Python 3.9 made that a bit easier to access), > as it's usually easier to get people to tell you what city/state > they're in, rather than whether daylight time will be active or not. > (It might take a little bit of translation to figure out that, for > instance, New Brunswick CA is America/Halifax, but that's not too hard > usually.) Letting tzinfo do all the work means you don't have to fret > about anyone's daylight saving transition dates, or whether they've > decided to change their clocks by half an hour to be different from > Japan's clocks, or to have DST not applicable during Ramadan, or to > have double DST, or double-negative DST. And yes, those are all real, > because you can't make up anything as insane as actual clock politics. So, given that it is a NUMERIC calculation, dispense with "New Brunswick CA is America/Halifax"; and avoid "Atlantic Time", "Atlantic Standard Time", "Atlantic Daylight Time", "AT", "ADT", or "AST", and express the time numerically: "17:00-3" Given that, someone at UTC-4 knows that his/her rendez-vous will be "1600", and I can figure it to be "0800" for me: 1700 - -3 = 20:00 (to calculate UTC), then UTC-4 = 16:00 and 1700 - -3 = 20:00 (to calculate UTC), then UTC+12 = 32:00, rounding to 24hrs: 08:00 (the next day) For many of us, the mental-calculations are relatively easy to manage. For Python the code is trivial. Computation is easier than terminology 'translation' (particularly when one has to research the terms first! - did you know what "ADT" meant?) You may have noticed that competent web-sites for courses, conferences, and the like, will offer 'widgets' that perform these calculations for the reader (based upon the time-zone reported by your client web-browser). This is very handy - and may I suggest, should be requirement for international operations - after all, don't we call it "the WORLD-WIDE web"? > (I find the Ireland situation particularly amusing. Northern Ireland, > being part of the UK, operates on London time, with clocks advancing > one hour for summer. The Republic of Ireland, on the other hand, has a > standard time which is one hour later than Greenwich's, but then they > subtract an hour during winter, returning to standard time in summer. > So when the rest of Europe adds an hour, Ireland stops subtracting > one. Clocks in Belfast and Dublin always show the same times.) Per @Alan's response, I have had 'hairy experiences' with time-zones and people 'doing their own thing'. It's all good-fun until someone misses a meeting and the boss... Teasing @Chris: I'm not sure why it should be amusing that two entities called 'Ireland' should have different time-zones (pot?kettle) - after all, does "Western Australia" use the same time-zone as "South Australia"? For that matter, the same as the bulk of the Australian population? The time-zone which perplexes me most, is India. This because it is not only a different hour, but also requires a 30-minute off-set - operating at UTC+5:30! Fortunately, like China, the entire country (officially) operates in the same time-zone. Accordingly, there is less consideration about working-out what time it is in Pune cf Kolkata, than between (say) San Francisco and Denver - although they are in the same country, are they in the same time-zone, or not? (they aren't!) -- Regards, =dn From rosuav at gmail.com Tue Aug 31 17:13:22 2021 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 1 Sep 2021 07:13:22 +1000 Subject: The sqlite3 timestamp conversion between unixepoch and localtime can't be done according to the timezone setting on the machine automatically. In-Reply-To: <5453b2a9-1a77-1aa1-e18e-f08904aaeabb@DancesWithMice.info> References: <715e310e-56e3-4c97-a454-770c709ea706n@googlegroups.com> <82b49bdc-36f3-2429-06cd-bd370ba3dfd7@DancesWithMice.info> <5453b2a9-1a77-1aa1-e18e-f08904aaeabb@DancesWithMice.info> Message-ID: On Wed, Sep 1, 2021 at 6:38 AM dn via Python-list wrote: > > Yeah. I do recommend making good use of the IANA tzinfo database > > though (especially since Python 3.9 made that a bit easier to access), > > as it's usually easier to get people to tell you what city/state > > they're in, rather than whether daylight time will be active or not. > > (It might take a little bit of translation to figure out that, for > > instance, New Brunswick CA is America/Halifax, but that's not too hard > > usually.) Letting tzinfo do all the work means you don't have to fret > > about anyone's daylight saving transition dates, or whether they've > > decided to change their clocks by half an hour to be different from > > Japan's clocks, or to have DST not applicable during Ramadan, or to > > have double DST, or double-negative DST. And yes, those are all real, > > because you can't make up anything as insane as actual clock politics. > > So, given that it is a NUMERIC calculation, dispense with "New Brunswick > CA is America/Halifax"; and avoid "Atlantic Time", "Atlantic Standard > Time", "Atlantic Daylight Time", "AT", "ADT", or "AST", and express the > time numerically: "17:00-3" > > Given that, someone at UTC-4 knows that his/her rendez-vous will be > "1600", and I can figure it to be "0800" for me: > > 1700 - -3 = 20:00 (to calculate UTC), then UTC-4 = 16:00 > and > 1700 - -3 = 20:00 (to calculate UTC), then UTC+12 = 32:00, > rounding to 24hrs: 08:00 > (the next day) No, that's not reliable... because of that abomination called Daylight Saving Time. Since I used New Brunswick, and since she's just gone online, I'll use a specific example: DeviCat livestreams at 6pm every Tuesday (and other times, but I'm going to focus on a weekly event here). Since she lives in NB, Canada, she defines that time by what IANA refers to as America/Halifax. I want to be there at the start of each stream, since I'm one of her moderators. But I live in a suburb of Melbourne - my clock shows what IANA calls Australia/Melbourne. To turn this into a purely mathematical calculation, you have to know exactly when she will go on or off DST, and when I will go on or off. Trying to turn it into an offset is going to fail badly as soon as you talk about "next Tuesday" and one of us is shifting DST this weekend. That's why it's better to let Python (or something) handle the whole thing. Don't concern yourself with exactly what the hour differences are, or which way DST is going, or anything; just convert Halifax time to Melbourne time. > For many of us, the mental-calculations are relatively easy to manage. > For Python the code is trivial. Computation is easier than terminology > 'translation' (particularly when one has to research the terms first! > - did you know what "ADT" meant?) I asked DeviCat what country and province ("state" in other regions) she lived in, and then confirmed with her that Halifax time was what her clock showed. The term "ADT" was never relevant. In a lot of situations, you don't even need to ask the human - you can let the web browser or desktop app report the timezone. The app can say something like "In order to schedule this event, will need to know your time zone. Is that okay?" and then send the IANA timezone name. > Teasing @Chris: I'm not sure why it should be amusing that two entities > called 'Ireland' should have different time-zones (pot?kettle) - after > all, does "Western Australia" use the same time-zone as "South > Australia"? For that matter, the same as the bulk of the Australian > population? Western Australia uses Australia/Perth timezone, and South Australia uses Australia/Adelaide. They're different base times from the east coast where I am by two hours, and half an hour, respectively; and they have different DST rules. On the east coast, we all have the same winter time, but in summer, Melbourne, Sydney, and Hobart move clocks forward, but Brisbane doesn't. > The time-zone which perplexes me most, is India. This because it is not > only a different hour, but also requires a 30-minute off-set - operating > at UTC+5:30! Yup, we got that too... Adelaide is half an hour back from Melbourne (UTC+9:30). But it gets worse. Kathmandu is on a quarter hour. And the Chatham Islands (part of New Zealand) are 12:45 ahead of UTC in winter, and then they add an hour of DST in summer, putting them at UTC+13:45. > Fortunately, like China, the entire country (officially) operates in the > same time-zone. Accordingly, there is less consideration about > working-out what time it is in Pune cf Kolkata, than between (say) San > Francisco and Denver - although they are in the same country, are they > in the same time-zone, or not? > (they aren't!) That would be convenient for working within China, but on the flip side, it means that geographically-nearby locations can have vastly different clocks. Oh, and one of those nearby locations is Nepal. So it's possible to step across a border and have your clock change from 3AM to 5:15AM. Yeah that's gotta be fun! But ultimately, it all just means that timezones are too hard for humans to handle, and we MUST handle them using IANA's database. It is the only way. ChrisA From 2QdxY4RzWzUUiLuE at potatochowder.com Tue Aug 31 17:16:13 2021 From: 2QdxY4RzWzUUiLuE at potatochowder.com (2QdxY4RzWzUUiLuE at potatochowder.com) Date: Tue, 31 Aug 2021 16:16:13 -0500 Subject: The sqlite3 timestamp conversion between unixepoch and localtime can't be done according to the timezone setting on the machine automatically. In-Reply-To: <5453b2a9-1a77-1aa1-e18e-f08904aaeabb@DancesWithMice.info> References: <715e310e-56e3-4c97-a454-770c709ea706n@googlegroups.com> <82b49bdc-36f3-2429-06cd-bd370ba3dfd7@DancesWithMice.info> <5453b2a9-1a77-1aa1-e18e-f08904aaeabb@DancesWithMice.info> Message-ID: On 2021-09-01 at 08:36:55 +1200, dn via Python-list wrote: > ... there is less consideration about working-out what time it is in > Pune cf Kolkata, than between (say) San Francisco and Denver - > although they are in the same country, are they in the same time-zone, > or not? (they aren't!) What about Phoenix? In the winter, it's the same time there as it is in San Francisco, but in the summer, it's the same time there as it is in Denver (Phoenix doesn't observe Daylight Saving Time). And then there's Indiana, a medium size state that tends to get ignored (they used to advertise "there's more than just corn in Indiana"). Most of Indiana is in US/Eastern, but the cities that are (for practical purposes) suburbs of Chicago are in US/Central (aka America/Chicago). ChrisA is right; you can't make this [stuff] up. Having lived in the United States my entire life (and being a nerd), I can confirm that (1) I'm used to it and handle it as well as possible, but (2) many people are not and don't. From rosuav at gmail.com Tue Aug 31 17:32:43 2021 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 1 Sep 2021 07:32:43 +1000 Subject: The sqlite3 timestamp conversion between unixepoch and localtime can't be done according to the timezone setting on the machine automatically. In-Reply-To: References: <715e310e-56e3-4c97-a454-770c709ea706n@googlegroups.com> <82b49bdc-36f3-2429-06cd-bd370ba3dfd7@DancesWithMice.info> <5453b2a9-1a77-1aa1-e18e-f08904aaeabb@DancesWithMice.info> Message-ID: On Wed, Sep 1, 2021 at 7:17 AM <2QdxY4RzWzUUiLuE at potatochowder.com> wrote: > > On 2021-09-01 at 08:36:55 +1200, > dn via Python-list wrote: > > > ... there is less consideration about working-out what time it is in > > Pune cf Kolkata, than between (say) San Francisco and Denver - > > although they are in the same country, are they in the same time-zone, > > or not? (they aren't!) > > What about Phoenix? In the winter, it's the same time there as it is in > San Francisco, but in the summer, it's the same time there as it is in > Denver (Phoenix doesn't observe Daylight Saving Time). I prefer to say: In winter, San Francisco (or Los Angeles) is the same as Phoenix, but in summer, Los Angeles changes its clocks away, and Denver changes to happen to be the same as Phoenix. > And then there's Indiana, a medium size state that tends to get ignored > (they used to advertise "there's more than just corn in Indiana"). Most > of Indiana is in US/Eastern, but the cities that are (for practical > purposes) suburbs of Chicago are in US/Central (aka America/Chicago). At least the US has governed DST transitions. As I understand it, any given city has to follow one of the standard time zones, and may EITHER have no summer time, OR transition at precisely 2AM/3AM local time on the federally-specified dates. (I think the EU has also mandated something similar for member states.) If we could abolish DST world-wide, life would be far easier. All the rest of it would be easy enough to handle. > ChrisA is right; you can't make this [stuff] up. Yeah. And if you think you've heard it all, sign up for the tzdata-announce mailing list and wait for the next phenomenon. I think Egypt (Africa/Cairo) is currently in the lead for weirdest timezone change, for (with short notice) announcing that they'd have DST during summer but not during Ramadan. Since "summer" is defined by a solar calendar and "Ramadan" is defined by a lunar calendar, that means the DST exclusion might happen entirely in winter (no effect), at one end or other of summer (shortens DST, just changes the dates), or in the middle of summer (DST on, DST off, DST on, DST off, in a single year). But they will, at some point, be eclipsed by an even more bizarre timezone change. I don't dare try to predict what will happen, because I know that the reality will be even worse.... > Having lived in the United States my entire life (and being a nerd), I > can confirm that (1) I'm used to it and handle it as well as possible, > but (2) many people are not and don't. Yup, absolutely. I've been working internationally for a number of years now, so my employment has been defined by a clock that isn't my own. I got used to it and developed tools and habits, but far too many people don't, and assume that simple "add X hours" conversions suffice. ChrisA From 2QdxY4RzWzUUiLuE at potatochowder.com Tue Aug 31 17:53:14 2021 From: 2QdxY4RzWzUUiLuE at potatochowder.com (2QdxY4RzWzUUiLuE at potatochowder.com) Date: Tue, 31 Aug 2021 16:53:14 -0500 Subject: The sqlite3 timestamp conversion between unixepoch and localtime can't be done according to the timezone setting on the machine automatically. In-Reply-To: References: <715e310e-56e3-4c97-a454-770c709ea706n@googlegroups.com> <82b49bdc-36f3-2429-06cd-bd370ba3dfd7@DancesWithMice.info> <5453b2a9-1a77-1aa1-e18e-f08904aaeabb@DancesWithMice.info> Message-ID: On 2021-09-01 at 07:32:43 +1000, Chris Angelico wrote: > On Wed, Sep 1, 2021 at 7:17 AM <2QdxY4RzWzUUiLuE at potatochowder.com> wrote: > > What about Phoenix? In the winter, it's the same time there as it is in > > San Francisco, but in the summer, it's the same time there as it is in > > Denver (Phoenix doesn't observe Daylight Saving Time). > > I prefer to say: In winter, San Francisco (or Los Angeles) is the same > as Phoenix, but in summer, Los Angeles changes its clocks away, and > Denver changes to happen to be the same as Phoenix. Not exactly. Sort of. Phoenix and Denver are both in America/Denver (aka US/Mountain), but only Denver observes DST. San Francisco and Los Angeles are both in America/Los_Angeles, and both observe DST. > At least the US has governed DST transitions. As I understand it, any > given city has to follow one of the standard time zones, and may > EITHER have no summer time, OR transition at precisely 2AM/3AM local > time on the federally-specified dates. (I think the EU has also > mandated something similar for member states.) That's my understanding, too. > If we could abolish DST world-wide, life would be far easier. All the > rest of it would be easy enough to handle. Agreed. > ... I think Egypt (Africa/Cairo) is currently in the lead for weirdest > timezone change ... Yeah, I read about that somewhere. Remember when the Pope declared that September should skip a bunch of days? > > Having lived in the United States my entire life (and being a nerd), I > > can confirm that (1) I'm used to it and handle it as well as possible, > > but (2) many people are not and don't. > > Yup, absolutely. I've been working internationally for a number of > years now, so my employment has been defined by a clock that isn't my > own. I got used to it and developed tools and habits, but far too many > people don't, and assume that simple "add X hours" conversions > suffice. Way back in the 1990s, I was working with teams in Metro Chicago, Tel Aviv, and Tokyo (three separate teams, three really separate time zones, at least two seaprate DST transition dates). I changed my wristwatch to 24 hour time (and never looked back). I tried UTC for a while, which was cute, but confusing. From rosuav at gmail.com Tue Aug 31 18:10:12 2021 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 1 Sep 2021 08:10:12 +1000 Subject: The sqlite3 timestamp conversion between unixepoch and localtime can't be done according to the timezone setting on the machine automatically. In-Reply-To: References: <715e310e-56e3-4c97-a454-770c709ea706n@googlegroups.com> <82b49bdc-36f3-2429-06cd-bd370ba3dfd7@DancesWithMice.info> <5453b2a9-1a77-1aa1-e18e-f08904aaeabb@DancesWithMice.info> Message-ID: On Wed, Sep 1, 2021 at 7:54 AM <2QdxY4RzWzUUiLuE at potatochowder.com> wrote: > > On 2021-09-01 at 07:32:43 +1000, > Chris Angelico wrote: > > > On Wed, Sep 1, 2021 at 7:17 AM <2QdxY4RzWzUUiLuE at potatochowder.com> wrote: > > > > What about Phoenix? In the winter, it's the same time there as it is in > > > San Francisco, but in the summer, it's the same time there as it is in > > > Denver (Phoenix doesn't observe Daylight Saving Time). > > > > I prefer to say: In winter, San Francisco (or Los Angeles) is the same > > as Phoenix, but in summer, Los Angeles changes its clocks away, and > > Denver changes to happen to be the same as Phoenix. > > Not exactly. Sort of. Phoenix and Denver are both in America/Denver > (aka US/Mountain), but only Denver observes DST. San Francisco and Los > Angeles are both in America/Los_Angeles, and both observe DST. America/Phoenix is a separate time zone from America/Denver. During winter they represent the same time, but during summer, Phoenix doesn't change its offset, and Denver does. (San Francisco isn't an IANA timezone; the city precisely follows Los Angeles time.) > > ... I think Egypt (Africa/Cairo) is currently in the lead for weirdest > > timezone change ... > > Yeah, I read about that somewhere. Remember when the Pope declared that > September should skip a bunch of days? Well, that's from transitioning from the Julian calendar to the Gregorian. The same transition was done in different countries at different times. The Pope made the declaration for the Catholic church in 1582, and all countries whose official religion was Catholic changed at the same time; other countries chose their own schedules for the transition. Notably, Russia converted in 1918, immediately after the "October Revolution", which happened on the 25th of October on the Julian calendar, but the 7th of November on the Gregorian. > Way back in the 1990s, I was working with teams in Metro Chicago, Tel > Aviv, and Tokyo (three separate teams, three really separate time zones, > at least two seaprate DST transition dates). I changed my wristwatch to > 24 hour time (and never looked back). I tried UTC for a while, which > was cute, but confusing. I tried UTC for a while too, but it became easier to revert to local time for my watch and just do the conversions directly. Perhaps, in the future, we will all standardize on UTC, and daylight time will be a historical relic. And then, perhaps, we will start getting frustrated at relativity-based time discrepancies ("it's such a pain scheduling anything with someone on Mars, their clocks move faster than ours do!"). ChrisA From python at mrabarnett.plus.com Tue Aug 31 18:18:02 2021 From: python at mrabarnett.plus.com (MRAB) Date: Tue, 31 Aug 2021 23:18:02 +0100 Subject: The sqlite3 timestamp conversion between unixepoch and localtime can't be done according to the timezone setting on the machine automatically. In-Reply-To: References: <715e310e-56e3-4c97-a454-770c709ea706n@googlegroups.com> <82b49bdc-36f3-2429-06cd-bd370ba3dfd7@DancesWithMice.info> <5453b2a9-1a77-1aa1-e18e-f08904aaeabb@DancesWithMice.info> Message-ID: <4d5d265c-59f0-8559-4b35-22695ad4a3e2@mrabarnett.plus.com> On 2021-08-31 22:53, 2QdxY4RzWzUUiLuE at potatochowder.com wrote: > On 2021-09-01 at 07:32:43 +1000, > Chris Angelico wrote: > >> On Wed, Sep 1, 2021 at 7:17 AM <2QdxY4RzWzUUiLuE at potatochowder.com> wrote: > >> > What about Phoenix? In the winter, it's the same time there as it is in >> > San Francisco, but in the summer, it's the same time there as it is in >> > Denver (Phoenix doesn't observe Daylight Saving Time). >> >> I prefer to say: In winter, San Francisco (or Los Angeles) is the same >> as Phoenix, but in summer, Los Angeles changes its clocks away, and >> Denver changes to happen to be the same as Phoenix. > > Not exactly. Sort of. Phoenix and Denver are both in America/Denver > (aka US/Mountain), but only Denver observes DST. San Francisco and Los > Angeles are both in America/Los_Angeles, and both observe DST. > >> At least the US has governed DST transitions. As I understand it, any >> given city has to follow one of the standard time zones, and may >> EITHER have no summer time, OR transition at precisely 2AM/3AM local >> time on the federally-specified dates. (I think the EU has also >> mandated something similar for member states.) > > That's my understanding, too. > [snip] In the EU, DST in the member states changes at the same time. It's not like the US where it ripples across the timezones, so the differences vary during the change. It all happens in one go. From rosuav at gmail.com Tue Aug 31 18:31:10 2021 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 1 Sep 2021 08:31:10 +1000 Subject: The sqlite3 timestamp conversion between unixepoch and localtime can't be done according to the timezone setting on the machine automatically. In-Reply-To: <4d5d265c-59f0-8559-4b35-22695ad4a3e2@mrabarnett.plus.com> References: <715e310e-56e3-4c97-a454-770c709ea706n@googlegroups.com> <82b49bdc-36f3-2429-06cd-bd370ba3dfd7@DancesWithMice.info> <5453b2a9-1a77-1aa1-e18e-f08904aaeabb@DancesWithMice.info> <4d5d265c-59f0-8559-4b35-22695ad4a3e2@mrabarnett.plus.com> Message-ID: On Wed, Sep 1, 2021 at 8:22 AM MRAB wrote: > > [snip] > In the EU, DST in the member states changes at the same time. It's not > like the US where it ripples across the timezones, so the differences > vary during the change. It all happens in one go. > Ah, good to know. I think that actually makes a lot of sense; in the US, they try to let everyone pretend that the rest of the world doesn't exist ("we always change at 2AM"), but in Europe, they try to synchronize for the convenience of commerce ("everyone changes at 1AM UTC"). A quick browse of Wikipedia suggests that some European countries (outside of the EU, which mandates DST transitions) have constant year-round UTC offsets. In theory, there could be a non-EU country that observes DST with different dates, but I can't find any examples. Here's hoping, hehe. ChrisA From barry at barrys-emacs.org Tue Aug 31 19:02:10 2021 From: barry at barrys-emacs.org (Barry) Date: Wed, 1 Sep 2021 00:02:10 +0100 Subject: urgent Message-ID: ? > On 31 Aug 2021, at 16:53, jak wrote: > > ?Il 31/08/2021 03:05, Python ha scritto: >> Hari wrote: >>> i was download ur python software but it is like boring user interface for >>> me like young student to learn ,can u have any updates? >> God, let me die please... > > Oh no, please don't speak in that way ... evidently now that python has > reached its tenth version its prompt is a little boring. It may need to > be replaced. You could open a competition notice to vote on the new > prompt. I would vote for: > > :^P> The big problem with >>> is that it means a third level quote in email clients. So when people cut-n-paste REPL output it?s formatted badly by email clients. A prompt that avoided that issue would be nice. >>> print(?this is not a quoted reply?) Barry > > rofl > -- > https://mail.python.org/mailman/listinfo/python-list From rosuav at gmail.com Tue Aug 31 19:06:06 2021 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 1 Sep 2021 09:06:06 +1000 Subject: urgent In-Reply-To: References: Message-ID: On Wed, Sep 1, 2021 at 9:03 AM Barry wrote: > > > > > On 31 Aug 2021, at 16:53, jak wrote: > > > > ?Il 31/08/2021 03:05, Python ha scritto: > >> Hari wrote: > >>> i was download ur python software but it is like boring user interface for > >>> me like young student to learn ,can u have any updates? > >> God, let me die please... > > > > Oh no, please don't speak in that way ... evidently now that python has > > reached its tenth version its prompt is a little boring. It may need to > > be replaced. You could open a competition notice to vote on the new > > prompt. I would vote for: > > > > :^P> > > The big problem with >>> is that it means a third level quote in email clients. > So when people cut-n-paste REPL output it?s formatted badly by email clients. > A prompt that avoided that issue would be nice. > > >>> print(?this is not a quoted reply?) > Welp, gonna have to convince people that the Python 3000 decision needs to be reversed :) https://www.python.org/dev/peps/pep-3099/#interactive-interpreter ChrisA From PythonList at DancesWithMice.info Tue Aug 31 19:19:03 2021 From: PythonList at DancesWithMice.info (dn) Date: Wed, 1 Sep 2021 11:19:03 +1200 Subject: The sqlite3 timestamp conversion between unixepoch and localtime can't be done according to the timezone setting on the machine automatically. In-Reply-To: References: <715e310e-56e3-4c97-a454-770c709ea706n@googlegroups.com> <82b49bdc-36f3-2429-06cd-bd370ba3dfd7@DancesWithMice.info> <5453b2a9-1a77-1aa1-e18e-f08904aaeabb@DancesWithMice.info> Message-ID: <575f2891-aee0-7973-60ea-1782d36efbbb@DancesWithMice.info> On 01/09/2021 09.13, Chris Angelico wrote: > On Wed, Sep 1, 2021 at 6:38 AM dn via Python-list > wrote: >>> Yeah. I do recommend making good use of the IANA tzinfo database >>> though (especially since Python 3.9 made that a bit easier to access), >>> as it's usually easier to get people to tell you what city/state >>> they're in, rather than whether daylight time will be active or not. >>> (It might take a little bit of translation to figure out that, for >>> instance, New Brunswick CA is America/Halifax, but that's not too hard >>> usually.) Letting tzinfo do all the work means you don't have to fret >>> about anyone's daylight saving transition dates, or whether they've >>> decided to change their clocks by half an hour to be different from >>> Japan's clocks, or to have DST not applicable during Ramadan, or to >>> have double DST, or double-negative DST. And yes, those are all real, >>> because you can't make up anything as insane as actual clock politics. >> >> So, given that it is a NUMERIC calculation, dispense with "New Brunswick >> CA is America/Halifax"; and avoid "Atlantic Time", "Atlantic Standard >> Time", "Atlantic Daylight Time", "AT", "ADT", or "AST", and express the >> time numerically: "17:00-3" >> >> Given that, someone at UTC-4 knows that his/her rendez-vous will be >> "1600", and I can figure it to be "0800" for me: >> >> 1700 - -3 = 20:00 (to calculate UTC), then UTC-4 = 16:00 >> and >> 1700 - -3 = 20:00 (to calculate UTC), then UTC+12 = 32:00, >> rounding to 24hrs: 08:00 >> (the next day) > > No, that's not reliable... because of that abomination called Daylight > Saving Time. Since I used New Brunswick, and since she's just gone > online, I'll use a specific example: > > DeviCat livestreams at 6pm every Tuesday (and other times, but I'm > going to focus on a weekly event here). Since she lives in NB, Canada, > she defines that time by what IANA refers to as America/Halifax. > > I want to be there at the start of each stream, since I'm one of her > moderators. But I live in a suburb of Melbourne - my clock shows what > IANA calls Australia/Melbourne. > > To turn this into a purely mathematical calculation, you have to know > exactly when she will go on or off DST, and when I will go on or off. > Trying to turn it into an offset is going to fail badly as soon as you > talk about "next Tuesday" and one of us is shifting DST this weekend. > > That's why it's better to let Python (or something) handle the whole > thing. Don't concern yourself with exactly what the hour differences > are, or which way DST is going, or anything; just convert Halifax time > to Melbourne time. OK, I admit it: I am so lazy that I don't use my fingers (nor my toes!) but expect my poor, over-worked (and under-paid) computer to calculate it all for me... I should have split the earlier explanation of two calculations, more clearly: Devicat can declare the start as "6pm" ("localisation") and state that the time-zone is UTC-3 - or as @MRAB suggested, translate it to "21:00 UTC" ("internationalisation") You (@Chris) then perform the second-half calculation, by adjusting the UTC-value to your time-zone. - and were I to attend, would personalise ("localise") the time similarly - but using my locality's (different) UTC-offset. I agree, the idea of 'Summer Time' is a thorough pain - even more-so when the host publishes in local-time but forgets that there will be a "spring forward" or "fall back" between the time of publication and the meeting-date! [the song says "Summer Time, and the living is easy". Unfortunately, Ella Fitzgerald isn't here to wrap her head around the problem, so I guess it's up to us...] Once again, it is a localisation/internationalisation problem. Why would you/I know, if and when, New Brunswick moves in/out of Summer Time? As described, it is another 'big ball of mud'. Far better to have the local deal with 'local issues', and for us to handle our own (time-zone) problems! (why should Devicat concern herself with MLB-based issues, or NZST, or wherever and etc?) [BTW: welcome to the first day of 'summer'!] Accordingly, when the N?o-Brunswickoise publishes "6pm", all the locals will be happy. If she adds UTC, or the locally-applicable UTC-offset (for Summer-Time, or not), the international community can make their own and personal arrangements, without winding-through the opaque and arcane seasonal-adjustments described! Plus the virtue(?) of using International Standards! >> For many of us, the mental-calculations are relatively easy to manage. >> For Python the code is trivial. Computation is easier than terminology >> 'translation' (particularly when one has to research the terms first! >> - did you know what "ADT" meant?) > > I asked DeviCat what country and province ("state" in other regions) > she lived in, and then confirmed with her that Halifax time was what > her clock showed. The term "ADT" was never relevant. Ah, but we are back to the original complaint about "CST" or "China Time". The "New Brunswick" in Canada is quite close to the "New Brunswick" in New Jersey (USA) - in physical distance, but the two are in distinct time-zones. (Yes, you did say "CA", but easily 'missed' - by author and reader alike) Confusing the two New Brunswick-s would make you late-to-the-party! > In a lot of situations, you don't even need to ask the human - you can > let the web browser or desktop app report the timezone. The app can > say something like "In order to schedule this event, will need to > know your time zone. Is that okay?" and then send the IANA timezone > name. Those are the better publishers. Too many do not - have yet to figure-out the implications of the words behind "www". Sigh! (have been glad to hear others grumping about the expression of times - it's not just me then!) >> Teasing @Chris: I'm not sure why it should be amusing that two entities >> called 'Ireland' should have different time-zones (pot?kettle) - after >> all, does "Western Australia" use the same time-zone as "South >> Australia"? For that matter, the same as the bulk of the Australian >> population? > > Western Australia uses Australia/Perth timezone, and South Australia > uses Australia/Adelaide. They're different base times from the east > coast where I am by two hours, and half an hour, respectively; and > they have different DST rules. > > On the east coast, we all have the same winter time, but in summer, > Melbourne, Sydney, and Hobart move clocks forward, but Brisbane > doesn't. Did I say that "Summer Time" is a pain? When (ordinary) folk try to explain it to me, they talk about 'the farmers' and agriculture. Every dairy farmer I've spoken with says it's all too-stupid - instead of milking at 0500, they start at 4am - no cow wears a watch! All this extra daylight is not good anyway - it fades the curtains more quickly! Living in the tropics I can't say I ever missed the sleep-disturbances caused by Summer time! >> The time-zone which perplexes me most, is India. This because it is not >> only a different hour, but also requires a 30-minute off-set - operating >> at UTC+5:30! > > Yup, we got that too... Adelaide is half an hour back from Melbourne > (UTC+9:30). But it gets worse. Kathmandu is on a quarter hour. And the > Chatham Islands (part of New Zealand) are 12:45 ahead of UTC in > winter, and then they add an hour of DST in summer, putting them at > UTC+13:45. ...the pain keeps getting worse... >> Fortunately, like China, the entire country (officially) operates in the >> same time-zone. Accordingly, there is less consideration about >> working-out what time it is in Pune cf Kolkata, than between (say) San >> Francisco and Denver - although they are in the same country, are they >> in the same time-zone, or not? >> (they aren't!) > > That would be convenient for working within China, but on the flip > side, it means that geographically-nearby locations can have vastly > different clocks. Oh, and one of those nearby locations is Nepal. So > it's possible to step across a border and have your clock change from > 3AM to 5:15AM. Yeah that's gotta be fun! Been there. Done that. It is! (not that specific border-crossing) "Jet lag" is one thing. Switching hemispheres I find dislocating. Having one's 'clock' switched by amounts other than round-hour amounts is just plain cruel! > But ultimately, it all just means that timezones are too hard for > humans to handle, and we MUST handle them using IANA's database. It is > the only way. I had (still have) a 'digi-ana' watch. It shows local time using the (analog) hands, and keeps 'home time' as a (smaller) digital display. Similarly, a travel alarm clock with a rotational-switch on the front, allowing the time (and/or the alarm time) to be set and displayed using any time-zone (not counting the half- and quarter-hour off-sets. Grrr!) PS I think my (Linux) computer is basically set to UTC. The desktop performs localisation. Then I added a 'widget' which extends the usual clock to give World Times. Failing that, there are numerous web-sites which offer time-translations or clocks showing times at chosen locales. The Internet 'standard' which "defines a date and time format for use in Internet protocols" is RFC3339: https://datatracker.ietf.org/doc/html/rfc3339 It describes itself as "a profile of the ISO 8601 standard" ISO do not publish their standards on the web (nor for $free) Wikipedia has good coverage of ISO 8601, starting at https://en.wikipedia.org/wiki/ISO_8601 Python's (and *nix - but not MS-Win) times are managed through the "tzdb". This was recently updated/upgraded with "PEP 615 -- Support for the IANA Time Zone Database in the Standard Library": https://www.python.org/dev/peps/pep-0615/ (implemented in Python 3.9) (there are other (accepted and implemented) PEPs dealing with 'time', eg improving accuracy to parts of a second, dealing with the "fold" ('losing' or 'duplicating' times/timestamps caused by Daylight Saving clock shifts), etc.) The tzdb is maintained by IANA (the Internet Assigned Numbers Authority): https://www.iana.org/time-zones; which is where we find such terms as "America/Halifax". It aims to handle the pain of "time zone boundaries, UTC offsets, and daylight-saving rules". However, it is not a standard! A couple of our training-courses' web-refs [usual disclaimer]: https://www.w3.org/International/articles/definitions-time/index.en https://www.w3.org/International/core/2005/09/timezone.html If you still want to know more/have managed to keep your head in the game for all this time, there's an extensive discussion and list of resources at https://data.iana.org/time-zones/tz-link.html -- -- Regards, =dn From python at mrabarnett.plus.com Tue Aug 31 19:27:46 2021 From: python at mrabarnett.plus.com (MRAB) Date: Wed, 1 Sep 2021 00:27:46 +0100 Subject: The sqlite3 timestamp conversion between unixepoch and localtime can't be done according to the timezone setting on the machine automatically. In-Reply-To: References: <715e310e-56e3-4c97-a454-770c709ea706n@googlegroups.com> <82b49bdc-36f3-2429-06cd-bd370ba3dfd7@DancesWithMice.info> <5453b2a9-1a77-1aa1-e18e-f08904aaeabb@DancesWithMice.info> <4d5d265c-59f0-8559-4b35-22695ad4a3e2@mrabarnett.plus.com> Message-ID: <8649af10-a421-e152-d9e1-611b05739d42@mrabarnett.plus.com> On 2021-08-31 23:31, Chris Angelico wrote: > On Wed, Sep 1, 2021 at 8:22 AM MRAB wrote: >> >> [snip] >> In the EU, DST in the member states changes at the same time. It's not >> like the US where it ripples across the timezones, so the differences >> vary during the change. It all happens in one go. >> > > Ah, good to know. I think that actually makes a lot of sense; in the > US, they try to let everyone pretend that the rest of the world > doesn't exist ("we always change at 2AM"), but in Europe, they try to > synchronize for the convenience of commerce ("everyone changes at 1AM > UTC"). > > A quick browse of Wikipedia suggests that some European countries > (outside of the EU, which mandates DST transitions) have constant > year-round UTC offsets. In theory, there could be a non-EU country > that observes DST with different dates, but I can't find any examples. > Here's hoping, hehe. > It goes forwards on the last Sunday of March and back on the last Sunday of October. From rosuav at gmail.com Tue Aug 31 19:38:30 2021 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 1 Sep 2021 09:38:30 +1000 Subject: The sqlite3 timestamp conversion between unixepoch and localtime can't be done according to the timezone setting on the machine automatically. In-Reply-To: <575f2891-aee0-7973-60ea-1782d36efbbb@DancesWithMice.info> References: <715e310e-56e3-4c97-a454-770c709ea706n@googlegroups.com> <82b49bdc-36f3-2429-06cd-bd370ba3dfd7@DancesWithMice.info> <5453b2a9-1a77-1aa1-e18e-f08904aaeabb@DancesWithMice.info> <575f2891-aee0-7973-60ea-1782d36efbbb@DancesWithMice.info> Message-ID: On Wed, Sep 1, 2021 at 9:20 AM dn via Python-list wrote: > > On 01/09/2021 09.13, Chris Angelico wrote: > > On Wed, Sep 1, 2021 at 6:38 AM dn via Python-list > > wrote: > >>> Yeah. I do recommend making good use of the IANA tzinfo database > >>> though (especially since Python 3.9 made that a bit easier to access), > >>> as it's usually easier to get people to tell you what city/state > >>> they're in, rather than whether daylight time will be active or not. > >>> (It might take a little bit of translation to figure out that, for > >>> instance, New Brunswick CA is America/Halifax, but that's not too hard > >>> usually.) Letting tzinfo do all the work means you don't have to fret > >>> about anyone's daylight saving transition dates, or whether they've > >>> decided to change their clocks by half an hour to be different from > >>> Japan's clocks, or to have DST not applicable during Ramadan, or to > >>> have double DST, or double-negative DST. And yes, those are all real, > >>> because you can't make up anything as insane as actual clock politics. > >> > >> So, given that it is a NUMERIC calculation, dispense with "New Brunswick > >> CA is America/Halifax"; and avoid "Atlantic Time", "Atlantic Standard > >> Time", "Atlantic Daylight Time", "AT", "ADT", or "AST", and express the > >> time numerically: "17:00-3" > >> > >> Given that, someone at UTC-4 knows that his/her rendez-vous will be > >> "1600", and I can figure it to be "0800" for me: > >> > >> 1700 - -3 = 20:00 (to calculate UTC), then UTC-4 = 16:00 > >> and > >> 1700 - -3 = 20:00 (to calculate UTC), then UTC+12 = 32:00, > >> rounding to 24hrs: 08:00 > >> (the next day) > > > > No, that's not reliable... because of that abomination called Daylight > > Saving Time. Since I used New Brunswick, and since she's just gone > > online, I'll use a specific example: > > > > DeviCat livestreams at 6pm every Tuesday (and other times, but I'm > > going to focus on a weekly event here). Since she lives in NB, Canada, > > she defines that time by what IANA refers to as America/Halifax. > > > > I want to be there at the start of each stream, since I'm one of her > > moderators. But I live in a suburb of Melbourne - my clock shows what > > IANA calls Australia/Melbourne. > > > > To turn this into a purely mathematical calculation, you have to know > > exactly when she will go on or off DST, and when I will go on or off. > > Trying to turn it into an offset is going to fail badly as soon as you > > talk about "next Tuesday" and one of us is shifting DST this weekend. > > > > That's why it's better to let Python (or something) handle the whole > > thing. Don't concern yourself with exactly what the hour differences > > are, or which way DST is going, or anything; just convert Halifax time > > to Melbourne time. > > OK, I admit it: I am so lazy that I don't use my fingers (nor my toes!) > but expect my poor, over-worked (and under-paid) computer to calculate > it all for me... > > > I should have split the earlier explanation of two calculations, more > clearly: > > Devicat can declare the start as "6pm" ("localisation") > and state that the time-zone is UTC-3 > - or as @MRAB suggested, translate it to "21:00 UTC" > ("internationalisation") > > You (@Chris) then perform the second-half calculation, by adjusting the > UTC-value to your time-zone. > > - and were I to attend, would personalise ("localise") the time > similarly - but using my locality's (different) UTC-offset. Gotcha gotcha. Unfortunately that, while theoretically easier, is not correct; she streams at 6pm every week, which means that the UTC time is *different* in June and December. > I agree, the idea of 'Summer Time' is a thorough pain - even more-so > when the host publishes in local-time but forgets that there will be a > "spring forward" or "fall back" between the time of publication and the > meeting-date! Right. Which is basically guaranteed when it's a recurring event. > Accordingly, when the N?o-Brunswickoise publishes "6pm", all the locals > will be happy. > > If she adds UTC, or the locally-applicable UTC-offset (for Summer-Time, > or not), the international community can make their own and personal > arrangements, without winding-through the opaque and arcane > seasonal-adjustments described! > > Plus the virtue(?) of using International Standards! She'd have to either specify two different UTC times, or two different local times. Instead, it's safer to just have her publish one local time (since that's how she's defining things), and let us all convert directly to our own timezones every time. > The "New Brunswick" in Canada is quite close to the "New Brunswick" in > New Jersey (USA) - in physical distance, but the two are in distinct > time-zones. (Yes, you did say "CA", but easily 'missed' - by author and > reader alike) Fair point. I'm not familiar with New Brunswick, New Jersey, USA, but I know that there are a lot of those kinds of collisions. > > In a lot of situations, you don't even need to ask the human - you can > > let the web browser or desktop app report the timezone. The app can > > say something like "In order to schedule this event, will need to > > know your time zone. Is that okay?" and then send the IANA timezone > > name. > > Those are the better publishers. > > Too many do not - have yet to figure-out the implications of the words > behind "www". Sigh! > > (have been glad to hear others grumping about the expression of times - > it's not just me then!) Yup yup. That's why I keep trying to encourage people to post IANA city names where possible. In a lot of cases, I can just ask someone "So that's the same as Halifax time?" or "You mean 3pm New York time?" and it's fine; they don't need to know why I chose some particular city, but people who live in an area will know what the major nearby cities are. > When (ordinary) folk try to explain it to me, they talk about 'the > farmers' and agriculture. Every dairy farmer I've spoken with says it's > all too-stupid - instead of milking at 0500, they start at 4am - no cow > wears a watch! Yeah, I have no idea where the "farmers" explanation came from. Growing up, we had some friends in countrified areas, including a sheep farmer who showed us a ton of stuff about how shearing worked, how moronic sheep are, and how farming life actually operates. It's not uncommon for such people to have two clocks: Government Time and Sun Time. Like you say, no cow wears a watch! > "Jet lag" is one thing. Switching hemispheres I find dislocating. Having > one's 'clock' switched by amounts other than round-hour amounts is just > plain cruel! I learned to be completely flexible about things, and just slide into whatever clock the destination has. But it does get very confusing when you're transiting through some airport and your watch is wrong by a weird amount... > PS I think my (Linux) computer is basically set to UTC. The desktop > performs localisation. Then I added a 'widget' which extends the usual > clock to give World Times. Failing that, there are numerous web-sites > which offer time-translations or clocks showing times at chosen locales. Yes, that's how Linux systems run. I believe Windows always sets the battery-backed clock in local time though, making dual-booting kinda finicky. > Python's (and *nix - but not MS-Win) times are managed through the > "tzdb". This was recently updated/upgraded with "PEP 615 -- Support for > the IANA Time Zone Database in the Standard Library": > https://www.python.org/dev/peps/pep-0615/ (implemented in Python 3.9) Not sure what you mean by "tzdb" but I presume that's tzdata? Sometimes called the Olson database? The change in 3.9 is mainly to make tzdata more generally available, instead of depending on installing it from PyPI. But whatever your way of getting it, that's the database to look for. So many insanities. ChrisA From PythonList at DancesWithMice.info Tue Aug 31 19:53:31 2021 From: PythonList at DancesWithMice.info (dn) Date: Wed, 1 Sep 2021 11:53:31 +1200 Subject: The sqlite3 timestamp conversion between unixepoch and localtime can't be done according to the timezone setting on the machine automatically. In-Reply-To: References: <715e310e-56e3-4c97-a454-770c709ea706n@googlegroups.com> <82b49bdc-36f3-2429-06cd-bd370ba3dfd7@DancesWithMice.info> <5453b2a9-1a77-1aa1-e18e-f08904aaeabb@DancesWithMice.info> Message-ID: <64424d66-ce08-5bd2-0d67-9eb1f82162ae@DancesWithMice.info> > Yeah. And if you think you've heard it all, sign up for the > tzdata-announce mailing list and wait for the next phenomenon. I think > Egypt (Africa/Cairo) is currently in the lead for weirdest timezone > change, for (with short notice) announcing that they'd have DST during > summer but not during Ramadan. Since "summer" is defined by a solar > calendar and "Ramadan" is defined by a lunar calendar, that means the > DST exclusion might happen entirely in winter (no effect), at one end > or other of summer (shortens DST, just changes the dates), or in the > middle of summer (DST on, DST off, DST on, DST off, in a single year). > But they will, at some point, be eclipsed by an even more bizarre > timezone change. I don't dare try to predict what will happen, because > I know that the reality will be even worse.... Similar to the situation where a few US cities maintain a different time-zone to the rest of the(ir) state, our refinery (in the Middle East) maintained just such a Ramadan-clock. I think such might be quite a common practice (which I'll describe, below). When considered, and motivation aside, it's not so very different from schemes enabling employees to choose their personal start-time (usually within a range, eg "glide time"), ideas to reduce 'rush hour' grid-locks by spreading commuter start/finish times, etc. At the refinery (computer center), we started one (or was it two) hours earlier that usual - as close to dawn as possible, ie the beginning of the daily fast. "Western employees" could take regular breaks, and usually 'disappeared' for 'midday meal', somewhere around 1030~1130. Muslim employees had no breaks. In lieu, they went home early - to be able to sleep. Later came sunset-prayers, and thereafter breaking-the-fast. Typically, there would be activities, and more meals, during the night. Meantime, the non-Muslims maintained a short 'afternoon shift', going home commensurately early. Others in the community were totally confused: "Why didn't you answer your phone yesterday afternoon?", "a meeting at 0700 - you must be joking!", etc. The pattern and predictability were broken! I thought it was a fabulous idea, actually leaving the office on-time (for a change), and heading straight down to the beach for some wind-surfing... That said, it really messed with your head. People staggered-in and managed little output first-thing. (need I say more?) At a more amusing level: my door was literally always-open, and because my office was at the end of a corridor, colleagues required only a glance to see if I was 'available'. The door only closed for personal/confidential discussions or when I was 'out' - except during Ramadan when I didn't want to insult anyone by drinking tea, effectively in-public. So, when the door was closed for long periods, this confused my staff. Indeed, I would often be asked "where have you been?" when I'd been working-away at my desk all-along, but simply hadn't got up to open the door once 'the coast was clear'. Life's rich tapestry... In my case, I blame "Ramadan-hours" for 'flipping the switch' (in my head) and turning a late-night owl, and stereotypical techie/hacker; into an 'early bird'. Ironically such serves me well today - dealing with clients and colleagues on the other side of the planet, who much prefer me to wake-early, so that they don't have to interrupt their evenings at home... -- Regards, =dn From PythonList at DancesWithMice.info Tue Aug 31 20:07:20 2021 From: PythonList at DancesWithMice.info (dn) Date: Wed, 1 Sep 2021 12:07:20 +1200 Subject: The sqlite3 timestamp conversion between unixepoch and localtime can't be done according to the timezone setting on the machine automatically. In-Reply-To: <8649af10-a421-e152-d9e1-611b05739d42@mrabarnett.plus.com> References: <715e310e-56e3-4c97-a454-770c709ea706n@googlegroups.com> <82b49bdc-36f3-2429-06cd-bd370ba3dfd7@DancesWithMice.info> <5453b2a9-1a77-1aa1-e18e-f08904aaeabb@DancesWithMice.info> <4d5d265c-59f0-8559-4b35-22695ad4a3e2@mrabarnett.plus.com> <8649af10-a421-e152-d9e1-611b05739d42@mrabarnett.plus.com> Message-ID: <523b2de9-ff6c-f528-59f3-7b827bccf6cf@DancesWithMice.info> On 01/09/2021 11.27, MRAB wrote: > On 2021-08-31 23:31, Chris Angelico wrote: >> On Wed, Sep 1, 2021 at 8:22 AM MRAB wrote: >>> >>> [snip] >>> In the EU, DST in the member states changes at the same time. It's not >>> like the US where it ripples across the timezones, so the differences >>> vary during the change. It all happens in one go. >>> >> >> Ah, good to know. I think that actually makes a lot of sense; in the >> US, they try to let everyone pretend that the rest of the world >> doesn't exist ("we always change at 2AM"), but in Europe, they try to >> synchronize for the convenience of commerce ("everyone changes at 1AM >> UTC"). >> >> A quick browse of Wikipedia suggests that some European countries >> (outside of the EU, which mandates DST transitions) have constant >> year-round UTC offsets. In theory, there could be a non-EU country >> that observes DST with different dates, but I can't find any examples. >> Here's hoping, hehe. >> > It goes forwards on the last Sunday of March and back on the last Sunday > of October. and @Chris' point about the lack of synchronisation: ? Daylight saving starts each year at 2am on the last Sunday in September, and ends at 3am on the first Sunday in April. Daylight saving starts Daylight saving ends 26 September 2021 3 April 2022 ? https://www.govt.nz/browse/recreation-and-the-environment/daylight-saving/ Have learned something new about my adopted-country today! Apparently New Zealand was once one of those half-hour-out countries (until 1946). >From when no "Daylight Saving time" was recognised. In 1974 a trial took place, and after public debate, the idea extended - continuing today: https://www.govt.nz/browse/recreation-and-the-environment/daylight-saving/history-of-daylight-saving-in-nz/ To explain the rationale for "Daylight Saving", ie "Summer Time": ? The 2008 survey found that 82% of New Zealanders approved of the 2007 extension to the period of daylight saving time. The rationale for changing the time over the summer months is that more sunlight hours will fall in the early morning if standard time is applied year round. In summer, these early morning sunlight hours are seen as being wasted as many people are asleep at that time. If the sunlight hours are shifted to the evening, by way of daylight saving time, they are more useful. ? -- Regards, =dn From avigross at verizon.net Tue Aug 31 20:08:41 2021 From: avigross at verizon.net (Avi Gross) Date: Tue, 31 Aug 2021 20:08:41 -0400 Subject: urgent (actually NOT urgent at all.) References: <008e01d79ec5$85af19b0$910d4d10$.ref@verizon.net> Message-ID: <008e01d79ec5$85af19b0$910d4d10$@verizon.net> This is a bit sillier then some other discussions here! There are many programs (especially back when more command-line programs were used) that presented default prompts like "$" and many or most of them let you over-ride it. Can someone tell this person that if >>> is not pleasing, they can do something like: import sys sys.ps1 = "what do you wish Mistress? -=> " And this can be set per session or perhaps across all accounts in an installation as a default? Some people focus on minutiae rather than either accept a language as being what it is, or finding a different way that meets their needs. I occasionally have made the prompt empty for a while so I can more easily do cut and paste from it. All that is needed for some is to make whatever prompt be somewhat unique among the other prompts they normally face. Sure, on some screens there are ways to add color or even odd characters and graphics to some prompts but who needs sexy? Realistically, many of us do so much of the programming elsewhere as in some editor or environment, and especially a language like python where indentation levels are strictly a part of the language. -----Original Message----- From: Python-list On Behalf Of Barry Sent: Tuesday, August 31, 2021 7:02 PM Cc: Python-list at python.org Subject: Re: urgent ? > On 31 Aug 2021, at 16:53, jak wrote: > > ?Il 31/08/2021 03:05, Python ha scritto: >> Hari wrote: >>> i was download ur python software but it is like boring user >>> interface for me like young student to learn ,can u have any updates? >> God, let me die please... > > Oh no, please don't speak in that way ... evidently now that python > has reached its tenth version its prompt is a little boring. It may > need to be replaced. You could open a competition notice to vote on > the new prompt. I would vote for: > > :^P> The big problem with >>> is that it means a third level quote in email clients. So when people cut-n-paste REPL output it?s formatted badly by email clients. A prompt that avoided that issue would be nice. >>> print(?this is not a quoted reply?) Barry > > rofl > -- > https://mail.python.org/mailman/listinfo/python-list -- https://mail.python.org/mailman/listinfo/python-list From grant.b.edwards at gmail.com Tue Aug 31 12:16:18 2021 From: grant.b.edwards at gmail.com (Grant Edwards) Date: Tue, 31 Aug 2021 16:16:18 -0000 (UTC) Subject: urgent References: Message-ID: On 2021-08-29, Hari wrote: > i was download ur python software but it is like boring user > interface for me like young student to learn ,can u have any > updates? Check the calendar, it must be September again... Well, almost. -- Grant Edwards grant.b.edwards Yow! Did I do an INCORRECT at THING?? gmail.com From wlfraed at ix.netcom.com Tue Aug 31 12:46:02 2021 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Tue, 31 Aug 2021 12:46:02 -0400 Subject: Struggling to understand timedelta rpesentation when applying an offset for an hour earlier - why is days = -1? References: Message-ID: On Tue, 31 Aug 2021 03:59:52 -0700 (PDT), dcs3spp via Python-list declaimed the following: >I cannot understand why the resultant datetime.timedelta is days=-1, seconds=82800 (23 hours) . > Read the documentation... https://docs.python.org/3/library/datetime.html#timedelta-objects >Why is it not an hour earlier as seconds=-3600? Why is days = -1 when the resultant calculated date is the same, year, day, month?? """ and days, seconds and microseconds are then normalized so that the representation is unique, with 0 <= microseconds < 1000000 0 <= seconds < 3600*24 (the number of seconds in one day) -999999999 <= days <= 999999999 """ Note that microseconds and seconds are ALWAYS normalized to be a positive integer. So your input on -3600 is normalized to +82800 from the previous day. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From wlfraed at ix.netcom.com Tue Aug 31 12:57:59 2021 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Tue, 31 Aug 2021 12:57:59 -0400 Subject: Create a real-time interactive TUI using Python. References: Message-ID: On Tue, 31 Aug 2021 06:12:42 -0700 (PDT), "hongy... at gmail.com" declaimed the following: >I want to know whether python can be used to create real-time interactive TUI, as hstr [1] does. > Most of these utilities appear to rely upon embedding commands into the OS SHELL prompt. You could embed pretty much anything to be run as part of the prompt display. https://github.com/dvorka/hstr/blob/master/CONFIGURATION.md#bash-history-settings Since source for HSTR is available, nothing prevents you from recoding everything in Python -- though I'm fairly certain Python may be a bit slower unless you can take advantage of compiled C libraries (regex, perhaps). Based upon the animated GIF, you'll have to master the curses library from Python. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From michael.stemper at gmail.com Tue Aug 31 17:47:10 2021 From: michael.stemper at gmail.com (Michael F. Stemper) Date: Tue, 31 Aug 2021 16:47:10 -0500 Subject: The sqlite3 timestamp conversion between unixepoch and localtime can't be done according to the timezone setting on the machine automatically. In-Reply-To: References: <715e310e-56e3-4c97-a454-770c709ea706n@googlegroups.com> <82b49bdc-36f3-2429-06cd-bd370ba3dfd7@DancesWithMice.info> <5453b2a9-1a77-1aa1-e18e-f08904aaeabb@DancesWithMice.info> Message-ID: On 31/08/2021 16.13, Chris Angelico wrote: > > But ultimately, it all just means that timezones are too hard for > humans to handle, and we MUST handle them using IANA's database. It is > the only way. Tom Scott makes this point quite strongly on Computerphile: And amusingly. -- Michael F. Stemper Always remember that you are unique. Just like everyone else. From hongyi.zhao at gmail.com Tue Aug 31 20:35:38 2021 From: hongyi.zhao at gmail.com (hongy...@gmail.com) Date: Tue, 31 Aug 2021 17:35:38 -0700 (PDT) Subject: Create a real-time interactive TUI using Python. In-Reply-To: References: Message-ID: <3019e9c8-fcef-43e4-adca-0ee39b1902dcn@googlegroups.com> On Wednesday, September 1, 2021 at 12:49:51 AM UTC+8, Chris Angelico wrote: > On Wed, Sep 1, 2021 at 1:59 AM hongy... at gmail.com wrote: > > > > I want to know whether python can be used to create real-time interactive TUI, as hstr [1] does. > > > > [1] https://github.com/dvorka/hstr > > > Yes. The following are some python TUI framework libraries/projects I have discovered so far: https://github.com/pfalcon/picotui https://github.com/peterbrittain/asciimatics https://github.com/bczsalba/pytermgui https://github.com/GeorgeFilipkin/pulsemixer https://github.com/jwlodek/py_cui https://github.com/saulpw/visidata https://github.com/willmcgugan/textual https://github.com/urwid/urwid HY