Conversation
|
Thanks for this. I've got a "full" copy of cpython pathlib ported to micropython I've been meaning to submit here. I'm keen to compare the two and see if there's any more I'd like to add her, but at first glance this looks quite good. |
|
I just realized my implementation will not properly handle combining multiple |
… representation to not always be absolute
|
alright; should be good now; fixed all the bugs I could find and added more tests. |
|
Thanks @BrianPugh this looks useful! I don't have much familiarity with using Two quick notes, I will try and do a more detailed review later:
|
|
We could make it build on top of After looking through micropyhton-lib's As for the other feedback:
micropython's
As I said in the original post, it's just named |
|
It would be better to use unittest from this repo and run the tests with micropython rather than cpython :-) |
|
I'll give it a try later today; i've never actually used the bare I agree that the definitive testing should be done with micropython, but cpython has nice things like |
|
Ah, yes I see you've used pytest fixtures and .raises a bit in the test code. Eventually I want to get CI running here testing everything with micropython unittest so being compatible with that is desired - and unfortunately pytest cannot be ported easily to micropython. I'm not sure about the best way to replace the fixture usage, but at least unittest has a raises test: https://github.com/micropython/micropython-lib/blob/master/python-stdlib/unittest/unittest.py#L192 Otherwise the normal assert you've used in most places is good to go. |
|
I don't want to sign myself up for too much work, but after I look at |
|
You'll be popular of you do make a port of pytest - it's been regularly requested over the years! The real pytest makes significant use of things like metaclasses, the inspect module and other low level things micropython doesn't support. For a long time unittest was missing the ability to "find and run all the tests in the project" but that was added recently with the unittest.discover module. Yep a raises assert is already provided by unittest so no difficulty there :-) I don't remember what fixtures are, I should look at them... and yeah there's a million ways to mock but having a well documented set of tools to do it in a consistent way is always good. But most importantly, pytest is obviously popular, so having a module with matching API for the most popular aspects makes it easier to port existing code and bring in developers already experienced with pytest like yourself! |
I would argue that we don't really need this in
Ah sorry I forgot -- it actually does, but for some reason only enabled on STM32, Renesas, Unix, and Windows. We should enable this on all ports. So I guess go with hard-coded "/" for now and we can fix this later. |
|
alright, so I gave micropython-compatible-pytest more thought:
Assuming we primarily develop libraries using cpython and just want to do final testing with micropython, this brings us to the key issue: "whats the minimal subset of pytest that can be implemented in micropython without limiting pytest running on cpython?"
So, this is a long winded way of saying that I think a useful micropython-compatible-pytest would be a lot of work and couldn't actually be properly implemented given the current micropython implementation. If the pytest-port isn't "compatible enough" with the normal version, then there's really no point. As for this PR, where does this put us? I don't think i could change all the tests to work with micropyhton unittest since I need to mock a few calls (like |
I'll factor out the separator symbol as it is in Do we want me to add support for |
|
so actually; i'm going to leave the separator hardcoded for now; this MIGHT only cause issues with windows? I just say that because in order for it to really work, i'd have to change how root is reported, correct? I don't really have access to a windows machine for testing. |
Fwiw I never develop micropython libraries with cpython. There's enough minor corner cases in micropython/cpython compatibility and/or I'm often working with new micropython C features so I pretty much always use the micropython Unix port for all testing - including test-driven-development which is my preference. I'm more than happy to continue without pytest myself, as mentioned I'm already comfortable with unittest, but I'm also very keen to get all test _* files run in CI with micropython unittest - so will want them to all be compatible with that (eventually). |
|
so i'm working on porting the tests over to unittest, and in order to do so I'm going to implement some features of
|
|
I'll update the tests here once #573 is merged. |
|
Alright, I have migrated the pytest to unittest and it all runs as expected in micropython. Read for another review! |
Looking at the code I have the impression it might be worth a relatively small effort and fix this now already, at least partially. For example we have |
|
Using I'd rather defer the work to a future PR when the needs/requirements are more obvious. |
And isdir, isfile, abspath, possibly more.
That's a bit of a strange argument, seeing that pathlib itself is sort of the definition of bloat for the sake of DRY :P I mean, it's quite big already itself but is essentially os and os.path with mostly a bunch of very short functions on top of it just to avoid having to repeat 1 or 2 lines of code |
I think this is a bit unfair in both cases ;-) I personally see pathlib as an almost perfect evolution of python style and best practice - it makes application code shorter and imho infinitely more readable - similar to the evolution of string formatting -> f-strings. While I'm usually all-for avoiding any kind of duplication, in this case I definitely agree we should not make a dependency on os.path (two packages) just to pull in a single byte definition and a tiny join function. That's using quite a lot more flash use for little gain. |
|
so what would we like to do with this? |
I think this is a good idea to start with, just to eliminate the hard-coded constants. Eg: from micropython import const
_SEP = const("/") |
|
@dpgeorge addressed! |
I'd like to use pathlib, but then it should work at least partially for backslashes; as in: should be fine that internally it uses forward slashes since 99% of Windows APIs work with those but the public facing parts accepting paths should handle the backslashes. And the 'is root' needs a fix. Now, if this doesn't make it into the first version that's fine and I can implement it myself later on, but: I just don't see how that is going to happen without reusing code, that's just a bit too much and not straightforward enough to just duplicate. So if it's really such a problem to import os.path here, which will need all fixes for backslashes as well, then part of it could be implemented in the os module in C. |
|
I can see both sides of the discussion here:
I think in the long term we need to follow (2). As discussed above, already To make progress, I'm happy to merge this as-is and improve it later (ie factor code into |
|
I'm in favor of merging now and fixing later. Not that this refactor would be particularly complicated, but it would be nice to have more unittesting/CI as guard rails. I understand the desire for deduplicating code, but I think thats more of a bigger effort (needs to be fixed in multiple modules). Additionally, I think we need to formalize the deduplication/dependency trade-off. I know each case is different, but generally there needs to be an agreement of "how good/bad is it to include another dependency." Micropython package management has gotten better recently with mip, but its not quite at the level of cpython. |
|
OK, let's move forward and merge this, then in the future it can be improved if needed. Squashed and merged in 0051a5e |
Yes it's tricky to formalise this. For example, if you already use |
Here's my first stab at adding most of the common functionality of
pathlib.Path. I'd say that 99% of the common use-case support is there. Theglobfunctionality could use some work; currently it only supports a single"*"wildcard; however, this is the vast majority of common use-cases and it won't fail silently if non-supported glob patterns are provided.Currently the module is named
upathlib; this was just so that I could get it working with pytest. If someone could help me import it in tests without colliding with the builtinpathlib, that would be greatly appreciated!Unit tests require
pytest-mockto be installed.