Note: previous Dennis posts are in the Diary category.
So, I heaved the codebase over the finish line. There are a few features missing, some ergonomic issues, and some code that should really be different. Also, even with all of my tweaks, rewrites, and type annotations, it's still deficient in terms of quality, in some pretty serious ways.
Now that I'd like to take a break from touching this and reorient myself, it might be a good idea to provide some context for all of this.
Dennis is my second attempt to follow along with TStand90's roguelike tutorial. The previous attempt, Homunculus, was done against an earlier version of the tutorial over a period of several months last year. The two codebases are completely unrelated. Homunculus ended up stalling out before reaching the end of the tutorial, because I didn't see a good way to implement certain functional programming concepts in Python that I really wanted, and I got distracted working on Structured Data in an attempt to develop implementations for them. I've had trouble (very visibly so) giving the tutorial credit for providing a basic template of functionality; I've been really distracted by the way the tutorial ignores various good development practices, and the code samples are sometimes out of synch between boxes, within boxes, and with the code in the git repo. Nonetheless, without some form of example code to look at for implementing the relevant functionality, Dennis would not have been possible.
All that said, let's break things down some. Resources that went into Dennis:
- TStand90's tutorial
- pyenv and pyenv-virtualenv
- A few libraries and tools that I don't think I exercised to their fullest potential, such as structlog and pyreverse
- Various libraries and tools that I have more experience with so they didn't really register. (Mercurial, pytest, camel, coverage, mypy)
At a high level, I've been trying out Poetry for several projects because I don't feel like it's worth writing and maintaining a setup.py file, and a MANIFEST.in and whatever else is supposed to be in there. I've been using Poetry because it's the only alternative I know of that supports using src layout.
I've been trying out Nox recently because I've felt like, as opposed to tox, it is worth using a general-purpose programming language to define the kinds of tasks I'm doing. Nox's documentation mentions Invoke, and so I ended up using Invoke for tasks that don't logically fit into a virtual environment with a particular configuration of Dennis installed.
Homunculus stalled out because I felt like I didn't have a good way in Python to do destructuring with user-defined types, and so I made one, and ended up getting caught up in extending it and figuring out what functionality it "should" have. Coconut provides the baseline required for what I wanted the features to accomplish, so it allowed me to put aside questions of how it should work, and just use it. That said, there were a few hurdles:
- Where they overlap, Structured Data and Coconut have some key differences in behavior: Coconut's "data" classes don't override tuple-based truthiness logic, so I ended up hitting weird bugs until I remembered to explicitly check whether a value of a zero-length data type was None. Also, Coconut's "match" statement places requirements on the pattern that don't exist in Structured Data; Structured Data "structures" are constructed at runtime, so any expression can evaluate to a structure, in theory. In contrast, Coconut's match seems to require the exact class name in scope, which goes against many Python style guides when it comes to defining a class in one module and matching against it in another.
- I managed to get Coconut to compile, in strict mode with no warnings, to syntactically invalid Python.
- For the Mypy integration, it seems like Mypy should be more able to reason about some of the constructs Coconut generates.
- Coconut's tooling is not where I'd like it to be, in an ideal world. No equivalent to Jedi; the autocompletion was bizarre and weak, and it doesn't even complete stuff from the standard library, aside from builtins. I kept on tab-completing typing.Call to typing.callable, which isn't a thing. I haven't run across any formatters; I mainly reacted to this by often being lazy and writing really long lines.
One thing that has me feeling a little iffy towards Poetry is that it doesn't currently have a documented way to interact with generated code like Coconut produces. (See, I really don't want to commit the generated code—I tried it and gave up after a few days—so that means I'm ignoring it for convenience, which means that the only reason Poetry sees anything to build is that I'm not using Git.) I haven't noticed any issues with it in the absence of generated code. I really like the robust dependency resolution. BUT Coconut was one of the absolutely essential bits of tooling for this project.
Taken together, this kind of makes my feeling on Coconut that I'd like to extract out the functionality I'd least like to rewrite in-place, and somehow take a mulligan on Structured Data focusing on just that functionality. Maybe Python 3.8's features would be helpful for this kind of thing...
Python 3.8.0a4+ (heads/master:331a6a56e9, May 27 2019, 11:07:29) [Clang 10.0.0 (clang-1000.11.45.5)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> abc = "abc" >>> if (a, b, c) := abc: ... print(a, b, c) ... File "<stdin>", line 1 SyntaxError: cannot use named assignment with tuple
Nope. Another possibility would be looking into libraries like attrs to see if anything fits my use case particularly well. A mix of approaches might make sense, as well.
Miscellaneous notes from development... PEP 518 was only recently clarified, and I'm pretty sure I saw people who interpreted the pre-clarification wording as the opposite of the clarification.
Anyway, that's what was on my mind once I got done with Dennis. I'd like to do a few iterations of the "Seed" concept, then migrate the repo over somehow, and start iterating on factoring out libraries.
Note: previous Dennis posts are in the Diary category.