Tab Completion

I'm Tab Atkins Jr, and I wear many hats. I work for Google on the Chrome browser as a Web Standards Hacker. I'm also a member of the CSS Working Group, and am either a member or contributor to several other working groups in the W3C. You can contact me here.
Listing of All Posts

Hs̄lgn̈, ym tsr̄f gṅln̆k

Last updated:

Back when I was a young nerd in high school, coming home on a long bus ride from a Future Problem Solvers meetup with my best friends (again, NERRRRRRRDS), we came up the idea of speaking English backwards, for fun.

Eventually, I evolved this into a more structured attempt at an actual conlang (constructed language), Hs̄lgn̈, which ended up being spoken by me and one of my little brothers.

Hs̄lgn̈ is a pig-latin, a language derived directly from English. Pig-latins are common as first conlangs, because they let you avoid the tiresome task of developing a vocabulary and jump straight into the more fun stuff of phoneme shifts, conjugations, writing systems, etc., while always having a "speakable" language ready. The pig-latin-ness is more obvious if I write its name in the Latin orthography: Hsilgne. ^_^

So yeah, it's still just English backwards, with some letter changes, a different orthography (it's written "natively" with an abugida, where vowels are indicated as diacritics on the consonants, rather than being letters on their own like in an alphabet), and specific pronunciation and stress rules vaguely similar, but not identical, to English.

Converting Orthography

The basic rules are simple.

  1. Take an English word (we'll use "English" for this example), and reverse it: "Hsilgne".

  2. If there are any C or Q letters, replace them with Ks. If there is a double-R, replace it with a rolled-R (currently represented with "ð" in my automatic converter, but that's not a good letter to use). (No change for "Hsilgne".)

  3. Merge vowels into their preceding letters:

    • a vowel before a consonant merges in directly, with aeiou becoming the diacritics ȯöōŏo̊
    • otherwise, the diacritic gets put on the "null consonant", "o", like in the previous bullet point
    • if a vowel is followed by an R, also merge that in, with a tail on the consonant, like ç. (My auto-converter currently uses an under-tilda rather than a tail, like "ẇ̰", because it renders more reliably, but I like the look of a tail better.)

    After this you have Hs̄lgn̈ - the "si" became "s̄", and the "ne" became "n̈".

Pronunciation

  • Vowels are pronounced like the English "long" vowels: ḃ=bay, b̈=bee, b̄=buy, b̆=bow (like "bow and arrow", b̊=boo.
  • Vowel-R blends are pronounced like Spanish: ḃ̰=bar, b̰̈=bear, b̰̄=beer, b̰̆=bore, b̰̊=boo-er (or t̰̊=tour)
  • An unvoweled consonant following a voweled one (like the "t" in ḃt) is pronounced as the final consonant of the syllable the voweled consonant forms (so ḃt is pronounced like "bait"), unless it's a "soft" consonant (r, y, h, l, or w), or it's followed by the same consonant again. So, for example, in "ṁy" the y is not part of the ṁ syllable, it forms a separate syllable. Similarly, r̈tṫm is three syllables (r̈)(t)(ṫm) (ree-teh-tame) - the first "t" doesn't merge into the r̈ syllable because it's followed by another "t".
  • When an unvoweled consonant isn't pronounced as the final consonant of the preceding letter, it uses the "default vowel", pronounced like "eh". (This often shortens to ə, the schwa.) So ṁy is pronounced like "may-yeh".

This means that Hs̄lgn̈ has five syllables: (H)(s̄)(l)(g)(n̈). Of the two voweled consonants, one is followed by a soft consonant, and the other ends the word, so all the unvoweled consonants get the default vowel instead: heh-sigh-leh-geh-nee

Stress

The syllable to stress is always one of the last three: if either of the last two syllables are "hard" voweled consonants, choose the last such; otherwise if either of the last two syllables are "soft" voweled consonants, choose the first such; otherwise the third-from-last syllable (or as close as you can get if there's less than three syllables).

So in Hs̄lgn̈ the stress is placed on the n̈ (heh-sigh-leh-geh-NEE), since it's the last syllable and is a "hard" voweled consonant. On the other hand, in a word like mhtyhr, which consists entirely of unvoweled consonants, the stress is on the y (meh-heh-teh-YEH-heh-reh), as it's the third-from-last syllable. In a word like w̆ð̇, the stress is on the w̆, as both syllables are "soft" voweled consonants, so you choose the first one (WOH-rray).

Other Things

There's more to the language, like conjugations and such, but they're more complex and I'm always tweaking them anyway. The most important bit is that verbs are written in the infinitive form, and any additional information that would be communication in the English tense is instead stated manually. So, for example, "this is good" would be written as "s̄ht öb d̆ŏg", using "be" instead of "is".

Automatic Converter

I have a pretty basic online converter available at https://www.xanthir.com/etc/hsilgne/. It doesn't do the verb conversion, and there might be some minor bugs in orthography, but it works surprisingly well. I used it to write all the words in this post, at least. ^_^

Some D&D Mistakes by the Sages (and how to fix them)

Last updated:

D&D 5e is an amazing game, and I sincerely love it and everything that its designers have done. (I've been following Mearls avidly since his days writing the Iron Heroes system, which got me into homebrew.) With anything so complex, tho, there will occasionally be mistakes in printed books. I can forgive this; I've sent plenty of emails that I proofread, only to immediately see an error I missed once it's too late.

But after printing, people often ask Mearls and Crawford (the Sages) about those ambiguities and mistakes, and they rule on them. Mostly these are quite good! But every once in a while they make what I feel is a big mistake, often by sticking with a textual literalism that results in something being overcomplicated for no good reason. Here's a few of those I've found, along with my preferred solutions:

Casting Spells with both Normal and Bonus Actions

In the core rules, there's a paragraph stating:

A spell cast with a bonus action is especially swift. You must use a bonus action on your turn to cast the spell, provided that you haven’t already taken a bonus action this turn. You can’t cast another spell during the same turn, except for a cantrip with a casting time of 1 action.

That is to say, if you cast a level 1-9 spell with your normal action, you can't cast one with your bonus action, and vice versa; you can cast a cantrip with the other action (or with both).

This is reasonably straightforward, and has some good justifications which I'll get into in a bit. But it gets complicated and bad when you mix in things that give the player an additional action, like the Fighter's Action Surge. What sorts of spells, precisely, can you cast with two normal actions and one bonus action?

Per the Sage Advice compendium, the answer is... it's complicated:

If you cast a spell, such as healing word, with a bonus action, you can cast another spell with your action, but that other spell must be a cantrip. Keep in mind that this particular limit is specific to spells that use a bonus action. For instance, if you cast a second spell using Action Surge, you aren’t limited to casting a cantrip with it.

This means you can use your normal action to cast a Fireball, and then Action Surge and cast another Fireball. But if you use a metamagic point to cast a Quickened Fireball with your bonus action, you cannot cast a normal Fireball, with either your normal action or the extra one from Action Surge.

(This even applies to spells cast as reactions between your turns - you can cast Counterspell or Hellish Rebuke as a reaction if you did the "fireball, action surge, fireball" thing, but if you cast a single quickened fireball and nothing else, you can't!?!)

This is obviously nonsensical! It means that taking more time to cast a spell gives you more time to cast an additional spell; that slowing down is sometimes the better answer. That's ridiculous, and means you have to metagame your actions sometimes to get a decent result. Further, this is just confusing; it doesn't correspond with our intuition for why this rule exists, so we'll either get it wrong in play or have to pay special attention to remember to apply it.

So let's look at the justification for the original rule, which is well-intentioned. There are two basic reasons for it:

  1. This heads off any unintentional combos that would be allowed by casting two spells in one turn, particularly as expansions add more spells and more combo potential. Cantrips aren't problematic to double up on; they're really simple and most of them closely resemble each other (just simple damage).
  2. More importantly, this is an anti-nova measure - it prevents players from burning thru more than one spell slot per turn, keeping their damage output more consistent with other players and slowing down the rate that they run out of steam. This was a major problem with casters in 3e, and the 5e devs addressed the issue with many complementary approaches such as this.

Maintaining these intents while removing the ambiguity, and keeping the rule as a whole as simple as possible, is really easy:

A character can only cast one non-cantrip spell during their turn, no matter what actions they have available to them. They can combine that spell with any number of cantrips that they have the actions for. This does not restrict spells cast not during your turn, such as a Hellish Rebuke cast as a reaction.

Boom, done. This is even a simpler way to state just the original rule, making it clearer that there aren't any ordering restrictions, and implying the intent behind the rule.

(Possible complication: this shuts down the possibility of a special ability that explicitly allows casting two spells in one turn. Such abilities, if they exist, can call themselves out as a special exception; or the rule can explicitly say "unless otherwise specified".)

This does shut down the "fireball, action surge, fireball" turn that was previously allowed by the rules/sage. If that is desired, then there's a somewhat more complex way of phrasing things that still allows it:

Within a single turn, a character can cast a non-cantrip spell with their normal action, or cast a non-cantrip spell with their bonus action, but not both. If they obtain additional actions by any means, such as the Fighter's Action Surge, there are no restrictions on using that action for casting.

This allows ", fireball, action surge, fireball" and "quickened fireball, , action surge, fireball", which matches player's intentions better than the current rules/sage interpretation.

Spell Components and Hands and Such

Spells can require Verbal (speaking magic words), Somatic (wiggling your hands), and/or Material (using a magic wand) components. Per Sage advice, a single free hand can handle both Somatic and Material components for a given spell (in other words, you can wiggle your wand around to satisfy both). This is fine so far.

Complications come with divine casters, which get to use a holy symbol for the Material component. This just has to be "presented" in some way - it can be on a necklace, or painted onto your shield, etc. Per explicit Sage Advice, this means that a Paladin or Cleric can hold a weapon in one hand, a shield with a holy symbol painted on it in the other, and still cast a spell with both Material and Somatic components.

The trouble is, this isn't possible for any other type of Material component! You can't combine a wand, instrument, etc with a functional shield or weapon, at least not in general. This gives divine casters an advantage over other casters, for no particular reason.

(Further, this "you can do somatic components with a shield in hand" is explicitly one of the benefits of the War Caster feat, which states "You can perform the somatic components of spells even when you have weapons or a shield in one or both hands.". So this gives divine casters a piece of a feat, that other casters don't get. Confusing!)

I think the correct way to solve this is to make the actual rules-significance of components slightly more abstract, something like:

When a spell has a Material component, it means you require a magical object on your person to act as a "focus" when casting the spell. This "focus" must be visibly presented when casting, tho it does not necessarily have to be held in a hand, and it is obvious to anyone watching you that you are casting a spell of some kind using that particular object.You are not required to hold the focus in a hand.

When a spell has a Somatic component, it means that casting the spell requires certain magical gestures. You can only perform these gestures when not restrained, and it is obvious to anyone watching you that you are casting a spell of some kind.

When a spell has a Verbal component, it means that casting the spell requires uttering certain magical incantations. You can only make these utterances when you not silenced or otherwise prevented from speaking, the incantations must be spoken at a normal speaking level, and it is obvious to anyone capable of hearing you that you are casting a spell of some kind.

This normalizes all of the component rules across casting classes, and makes it clearer what each one means, and when you might not be able to cast a particular spell due to inability to provide the components. For example, it's clear that you can prevent a caster from using Somatic spells by tying them up.

Avoiding Novas, or, Encouraging Dramatic Escalation in D&D

Last updated:

I (as you probably know from my previous post and others on this blog) love D&D, and roleplaying games in general. A recent tweet from @dungeonbastard brought up a problem that I'd never consciously noticed before, but now realize that I've been constantly fighting against.

When we play D&D, we pretend it's a narrative game, that we're telling a story. But that's just one layer - the actual mechanics of the game, which drive the story, are descended from wargaming. This creates a conflict of goals during scenes like combat - in stories, combat has a dramatic arc, with an opening, a build-up, and a climax where the characters pull out their strongest abilities; in wargames, action economy rules everything, and you want to minimize overkill, so it's almost always best to blow your strongest moves immediately (the so-called "nova") and then mop-up whatever's left. D&D is about roleplay, but it's also a game, and we play games to win, so this conflict is frustrating.

In the replies people had a lot of suggestions, often based on mechanics from games that explicitly have a stronger narrative focus, and which have crafted their mechanics to support it. One in particular I found extremely compelling, from a game called 13th Age, which was based on D&D but with a stronger focus on getting the mechanics to support the narrative.

The Escalation Die

The basic idea is that there's a special d6, preferably a large, special-looking one, called the Escalation Die. After the first round of combat, assuming it was exciting, you put it on the table turned to 1. Each round thereafter, as long as the combat stays exciting, you turn it to the next number, maxing out at 6. If things get dull (players being safe and defensive instead of pressing the attack), you can leave it at its current value, or even decrease it.

The players, then, get a bonus to all attacks, saves, and checks (and save DCs) equal to the current value of the Escalation Die. To compensate for this added bonus, all enemies get a +2 to their AC, so which is canceled out by round 3 of a combat.

The point of this is that when combat starts, players are less likely to hit, but after a few rounds, they have a substantial bonus. This means their big, flashy attacks are best saved for a few rounds, to maximize their chance of succeeding - instead of nova-ing at the start of battle, you spend the time setting yourself up and beginning the engagement.

To enhance the effect, you can tie the bigger, flashier class abilities to the Escalation Die as well - you can't use your highest level of spells, or your X/day abilities, or what-have-you, until the Escalation Die is at 3+ or something.

While most monsters don't pay attention to the Escalation Die (and thus the combat gets easier as it escalates), "boss" monsters do (so both parties hit more often).


All in all, I just really like this concept. The restrictions ensure that you don't pull out your flashy abilities until later in the fight, which is nice narratively, but it's not all downside - the escalating bonus is just genuinely good, and helps protect against the "everyone misses several times in a row" runs of bad luck that sometimes happens.

I think I'll introduce this to the campaign I'm running for my little brother. He's already shown the power of the Paladin's smites, and so restricting that by the Escalation Die seems like it would be fun. This is also a solo campaign, so his fights will either be solo or with a single companion run by me, and the decreased chance of a bad run of luck later in the battle will be really effective at preventing a bad-luck death.

Fantasy World: Spirits as Corporations, Gods as States

Last updated:

(This is another entry in my collection of fantasy world-building ideas.)

I've picked up the habit, from people like Doctorow and Stross, of thinking of corporations and other things that are large groupings of people as a lifeform all their own. We humans, as complex multi-cellular organisms, are made from living cells, heavily-adapted from previously free-living single-celled organisms, but don't share many traits with those cells - we're a pattern on top of them, forming a totally novel form of life, with motivations and behaviors dramatically different from those of our component cells.

Similarly, corporations act like living things, built out of component humans, but acting as a novel pattern on top of those humans. Very small companies are still dominated by the individual humans in them, but at a certain size they inevitably start acting like something new, something beyond the humans leading them. You can swap out the management of most companies, and the company will continue living on mostly unchanged - they're composed of independent structure that uses humans, but is not actually driven by humans, just as we humans use cells. (The analogy isn't perfect, of course - we humans are built of trillions of cells, so any one cell has approximately zero chance of influencing us (except in rare cases like a lucky cancer cell), but corporations are made of a comparatively much smaller number of humans, so individual humans can have a larger effect on the whole.)

Biological organisms survive by expending their stores of energy to hunt down other biological organisms, consuming them and gaining more calories than they spent, to distribute to the cells that they're made up of. (Only on the extreme margins do biologicals do other things for energy, like photosynthesis or chemosynthesis. Plants and bacteria are clearly on a separate order of life than humans and other animals.)

Similarly, economic organisms like corporations survive by expending money to develop product lines and advertising, to convince other economic organisms (humans, or other corporations) to give up some of their own money, which the corporation then distributes to the humans they're made up of. They survive if they gain more money than they spent.

There's a closely related entity to the corporation that lives a dramatically different lifestyle - the state. While states do still have a nucleus of humans that drive them and which need to be fed with money (government employees), the way they feed is completely different. Rather than convincing other economic entities to give up their money via advertising and such, states simply claim space, and any economic organisms living in that space have to pay taxes to the state for the privilege of living there. States do still compete to a point, making their spaces more attractive, or their laws friendlier, but for the most part the organisms they extract money from are a captive populace.

To put the analogy a little differently, states are the brontosauruses of the economy - huge, lumbering titans that feed on whatever's around, and more or less immune to attack unless they're young or already severely injured. Corporations are the carnivores - mostly small and feisty, grabbing money where they can, but occasionally growing large and old and fearsome.

Get To The Fantasy Already

Okay, so let's shift gears to my fantasy world.

The basics of my metaphysics is that the world exists simultaneously in two layers: a physical and a narrative. Things that happen in one layer are reflected in the other; this is the basis of how magic works. At its core the world does not look like our familiar physical world, as many physical processes are driven by things in the narrative layer.

For example, atomic physics as we know it doesn't exist - the world is instead composed of a small number of complex-at-their-core elements, as I explained in the earlier Magical Metaphysics post. Our physical world is mostly composed of Physical and Biological elements, with Mental, Divine, and Energetic elements playing a more transient role. (That is, Mental elements don't "stick around" as part of physical reality; they're generated by and affect the physical world, but don't have a stable existence on their own.) The narrative layer is the opposite - it's mostly Mental and Divine, with Physical, Biological, and Energetic elements playing only a transient role.

So, spiritual beings exist mostly in the narrative layer, composed of thoughts and moral forces. They're literally made of stories, and are fed by people thinking of them (or more strongly, by worshiping and devoting themselves to the spirit). Even just reading about a spirit in detail strengthens that spirit, as your own mental impressions feed into the narrative layer and reinforce their existence.

Now to D&D. I really like the Warlock class in 5e - it's fun and unique, and I end up mixing at least a few levels into most of my character concepts. But I absolutely abhor the default flavor given to them. They're cast as mini-Clerics, devoting themselves in some way to the entity they've made a pact with and draw power from. But the default pact-capable entities are all bad! The most neutral one is an Archfey, but 5e has tried hard to make it clear that the Fey are amoral as we understand morality. The other two are just straight up demons, and eldritch horrors from beyond reality. We're supposed to believe that people who have literally contracted with demons, or promised to bring chaos and corruption into the world for magical power won't be shunned, jailed, or killed on sight? It's just straight-up evil! This is hard enough to reconcile in a standard D&D game, where everyone can just conveniently ignore most of the implications, but it's extremely troublesome for worldbuilding, where I want to have Pact Magic be the easiest and most common form of magic among people.

So, I've recast things a bit. All spiritual beings of middling power are naturally subject to Pacts, which bind them against their will and allow people to draw power from them. Pacts are a deeply-worn groove in the narrative structure of reality, and it's well-known that forging a pact with an entity requires zero agreement from that entity - there's no implication that you agree with them at all. In fact, many holy organizations heavily use demonic pacts, with the goal of draining the power of the demons and limiting their influence on the world.

But it's not totally one-sided. As I said, spiritual/narrative entities survive on attention. Being aware of them, thinking about them, recording details of them for future generations to read - all of this supports their existence. Entities who are subject to pacts are actually made more secure in existence - they're less likely to be forgotten and fade away. Pacts require careful study of an entity, to form the proper binding circle and rites, and this sort of study and recording is exactly what they want and need.

(Becoming more powerful with pact magic does require aligning yourself with the being you've bound, but that doesn't mean morally aligning yourself with them. Narrative entities have various domains, and you can align yourself with one while ignoring the more distasteful ones. For example, many demons have are spiritually aligned with fire, and so embracing fire magic or what-have-you aligns you spiritually with them, enabling you to raise your binding and increase your power.)

Note that only middling-power entities are subject to pacts. Weak entities either don't have enough "heft" to be properly grabbed by a Pact, or simply don't have enough power to survive a binding - it's in the binder's best interests to find an entity that can actually supply the power they want to draw.

Powerful spiritual entities, on the other hand, are immune to pacts as a matter of their nature. Much as the corporate life structure transitions to the surface-similar but deep-different feeding structure of the state, at some point in their growth spirits might lay claim to some area in narrative-space directly. They're no longer trying to spread and strengthen their own story, they're squatting on the abstract idea of some story, so that whenever that particular narrative plays out in the world, even if the people don't acknowledge the entity at all, it's still able to draw power from it. These are what we would traditionally call Gods, with their Domains: a God of Murder, for example, is strengthened by any murder, regardless of how or why it was performed; a God of the Harvest is strengthened by any agriculture, regardless of what it is; etc. There's still a notion of space and location in this - there can be multiple murder Gods, each feeding off of a different area.

Direct devotion to the God is still more nourishing, of course, and so they are incentivized to maintain a priesthood and spread their individual stories as well. If they become forgotten and live only off of anonymous narratives, they're vulnerable to being displaced by a fresh god, flush with worship and narrative control and looking to expand or establish their Domain. That is how Gods die - not directly by the hand of anyone physical, but by being replaced by other Gods.

Newbie's Guide to Python Module Management

Last updated:

I've always been confused by Python modules and how they work, but was able to kinda muddle thru on my own, as I expect most of us do. I recently sat down and actually taught myself how they work, and I think I have a handle on them now. To test it, I refactored a chunk of code in one of my projects that was bothering me, and as far as I can tell, I did so successfully!

This post documents that process, to hopefully help others in figuring stuff out.

The Problem

My main open-source project, Bikeshed, has to maintain a set of data files. These get updated frequently, so users can call bikeshed update to get new data for them, straight from the data sources. Each data source gets its own independent processing; there's not really any shared code between the different data files.

Originally there were only two types of data, and I wasn't doing anything too complicated with either of them, so I just went ahead and crammed both of the update functions into the same file, update.py. Fast-forward two years, and I've now got six independent update functions in this file, and several of them have gotten substantially more complicated. Refactoring code into helper functions is becoming hard, because it makes it more difficult to find the "main" functions buried in the sea of code.

What I'd really like is for each independent updater function, and its associated suite of helper functions, to live in a separate file. But I've already got a lot of files in my project - it would be great to have them all grouped into a subfolder.

Intro to Python Packages/Modules

So each foo.py file in your project automatically defines a module, named foo. You can import these files and get access to their variables with from . import foo, or from .foo import someVariable. (This is using absolute package-relative imports, which you should be using, not the "implicit relative imports" that Python2 originally shipped with; the . indicates "look in this module's parent".)

Each foo folder in your project defines a package named foo, if the folder has an __init__.py file in it. Packages are imported exactly like modules, with from . import foo/etc; the only difference is that packages can contain submodules (and subpackages) in addition to variables. This is how you get imports like import foo.bar.baz - foo and bar are packages (with bar a subpackage of foo), baz is either a package or a module.

Whenever you import a package, Python will run the __init__.py file and expose its variables for importing. (This is all the global variable names the code in the module can see, including modules that that the code imports!) It also automatically exposes any submodules in the package, regardless of whether __init__.py imports them or not: you can write import foo.bar if the foo/ folder contains a bar.py file, without foo/__init__.py having to do anything special. (Same for nested packages.)

Finally, whenever you do a * import (like from foo import *), Python will go ahead and pull in all the variables that foo/__init__.py defines and dump them into your namespace, but it does not dump submodules in unless __init__.py explicitly imported them already. (This is because the submodules might not be supposed to be part of the public API, and importing may have side-effects, since it just runs an __init__.py, and you might not want those side-effects to automatically happen.) Instead, it looks to see if __init__.py defined a magical __all__ variable; if it did, it assumes it's a list of strings naming all the submodules that should be imported by a * import, and does so.

(AKA, if your __init__.py already imports all the submodules you use or intend to expose, you're fine. If there are more that __init__.py doesn't use, but you want to expose to *-imports, set __all__ = ["sub1", "sub2"] in __init__.py.)

The Solution

So now we have all the information we need.

Step 1 is creating an update/ folder, and adding a blank __init__.py file. We now have an update package ready to import, even tho it's empty right now.

Step 2 is copying out all the code into submodules; I created an update/updateCrossRefs.py file and copied the cross-ref updater code into it, and so on. Now that the code is in separate files, I can rename the updater functions to all be just def update() for simplicity; no need to mention what they're updating when that's already in the module name.

Now that the code has moved from a top-level module in my project to a submodule, their import statements are wrong - anything that mentions from . import foo will look in the update package, not the overall project. Easy to fix, I just have to change these to from .. import foo; you can add as many dots as you want to move further up the package tree if you need.

At this point I'm already mostly done; I can run import update, then later call update.updateCrossRefs.update(), and it magically works! The last step is in handling "global" code, and putting together a good __init__.py.

For Step 3, I have one leftover piece of code, the general update() function that updates everything (or whatever subset of stuff I want). This is the only function the outside world ever actually calls; it's the only thing that calls the more specific updaters.

There's a few ways to do this - you can just put it directly in __init__.py and call it a day. But that exposes the imports it uses, and I want to keep the update module’s API surface nice and clean. Instead, I create another submodule, main.py, and put the function over there. Then, in __init__.py, I just call from .main import update. Now the outside world can say from . import update, and then just call update.update(), without having to know that the function is actually defined in a submodule.

Now that this is all done, I can finally delete the original update.py file in my main project directory. It's empty at this point, after all. ^_^

The End Result

I end up with the following directory structure:

bikeshed/
  ...other stuff...
  update/
    __init__.py
    main.py
    updateCrossRefs.py
    updateBiblio.py
    ...

And my __init__.py just says:

from .main import update, fixupDataFiles

__all__ = ["updateCrossRefs", "updateBiblio", 
           "updateCanIUse", "updateLinkDefaults", 
           "updateTestSuites", "updateLanguages"]

Then my project code, which was already doing from . import update, and calling update.update() (or update.fixupDataFiles()), continues to work and never realizes anything has changed at all!