Closed qntm closed 1 year ago
Aside: what the heck is up with Python's module exports behaviour? There's seriously no way at all to prevent everything from being exported, even if the importer didn't specifically import it? This is completely bananas... JavaScript's system is far superior...
Aside: what the heck is up with Python's module exports behaviour? There's seriously no way at all to prevent everything from being exported, even if the importer didn't specifically import it?
I agree with your sentiment :)
In Python, the default is to export everything except in these cases:
_some_helper
is not automatically imported when importing the module defining it.__all__ = ("Foo", "Bar")
in a given module, only those names are imported by default.The default behaviour is kinda similar to each module declaring something like:
__all__ = [name for name in globals().keys() if not name.startswith('_')]
But that includes everything you've imported, too.
Usually, you want to define __all__ = ("…")
. My habit is typically to do that for every module/file:
class Pattern:
...
__all__ = (
'Pattern',
'parse_pattern',
'ParseError',
# …
)
Importantly, without unusual temporary-scoping jiggery-pokery, it's not straightforward to prevent someone manually importing something. Which is a nightmare for interface maintenance, unfortunately.
This is a complete overhaul of
greenery
.greenery.fsm
has been eliminated from the public API - this package is intended for manipulating regular expressions, and FSM-related capability is secondary to that, an implementation detail. If the FSM module is considered useful enough to warrant re-exposing, I may factor it out as its own package. For now, though, it's internal.greenery.lego
no longer exists. Instead the package's API consists only ofparse(string)
which returns aPattern
object, the methods on thosePattern
objects, and some bits and pieces noted in the documentation. This fixes #23.UpperCase
format. No clue why this wasn't the case before... (EDIT: because Python's own builtin classes likefrozenset
are lower case for some stupid reason, does Python ignore its own style guidelines?)lego
module has been extracted out into separate pieces:parse.py
handles parsing and is its own module, similarlybound.py
,multiplier.py
andcharclass.py
. However, due to the circularity, I wasn't able to split outmult.py
,conc.py
andpattern.py
- these still have to be lumped together in what is nowrxelems.py
. I might try to unscramble this sometime but it may be intractable. I was able to split out most of their dedicated unit tests, though.Pattern
and aMult
.hasattr
anywhere, although we do still have to useisinstance
andtype
in a few places. I consider this an unavoidable result ofMult
's multiplicand needing to potentially be either aCharclass
or a sub-Pattern
. I'm disinclined to sink any more work into trying to "resolve" this. Fixes #24.self.__dict__
(if any). Because all the classes here are immutable, we do still have to usesetattr
in several places right after object initialisation - I might try to minimise this sometime, but I consider it a low priority. Fixes #56.parse
, added support for the confusing scenario of negated charclass shorthand inside of square bracket charclesses, like[^\W]
,[123\D]
,[\s\S]
and so on. Fixes #35. Might tidy this up a little more later.module map.txt
, ditto.CHANGELOG.md
.