From 930f5beaa8aabd93f3f21dcf9b5760e8dc0d4917 Mon Sep 17 00:00:00 2001 From: Griatch Date: Tue, 16 Nov 2021 01:47:08 +0100 Subject: [PATCH] Add pygments parsing of code --- devblog/2014.html | 10 +- devblog/2015.html | 46 ++++---- devblog/2016.html | 10 +- devblog/2017.html | 40 ++++--- devblog/2018.html | 5 +- devblog/2019.html | 100 +++++++++--------- .../_src/{build_blog.py => build_devblog.py} | 31 +++++- stylesheets/styles.css | 5 +- 8 files changed, 132 insertions(+), 115 deletions(-) rename devblog/_src/{build_blog.py => build_devblog.py} (86%) diff --git a/devblog/2014.html b/devblog/2014.html index b47f732418..49dbf86c92 100644 --- a/devblog/2014.html +++ b/devblog/2014.html @@ -750,19 +750,17 @@

Digging around a bit I found googlecode2github. This download contains python scripts for converting the wiki as well as Issues. I didn't really get the issues-converter to work, so I had to find another solution for that (see next section).

All in all, the initial wiki conversion worked decently - all the pages were converted over and were readable. I was even to the point of declaring success when finding the damn thing messed up the links. Googe Code writes links like this: [MyLink Text to see on page]. The script converted this to [[MyLink|Text to see on page]]. Which may look fine except it isn't. GitHub actually wants the syntax in the inverse order: [[Text to see on page|MyLink]].

Furthermore, in Google Code's wiki, code blocks were marked with

-

-{{{   
+
{{{   
 
  <verbatim code>   
 
 }}}
+
-

In markdown, code blocks are created just by indenting the block by four spaces. The converter dutifully did this - but it didn't add empty lines above and below the block, which is another thing markdown requires. The result was that all code ended up mixed into the running text output.

I could have gone back and fixed the converter script, but I suspected there would be enough small things to fix anyway. So in the end I went through 80+ pages of fixing link syntax and adding empty lines by hand. After that I could finally push the first converted wiki version up to the GitHub wiki repository.

Some time later I also found that there is a way to let GitHub wiki pages use syntax highlighting for the language of your choice. The way to do this is to enclose your code blocks like this:

-

-```python  
+
```python  
 
   
 
@@ -771,8 +769,8 @@
   
 
 ``` 
+
-

This is apparently "GitHub-flavoured" markdown. So another stint into all the pages followed, to update everything for prettiness.

Converting Google Code Issues

I didn't want to loose our Issues from Google Code. I looked around a bit and tested some conversions for this (it helps to be able to create and delete repos on GitHub with abandon when things fail). I eventually settled on google-code-issues-migrator.

diff --git a/devblog/2015.html b/devblog/2015.html index 01bbbc7948..f1388b55f6 100644 --- a/devblog/2015.html +++ b/devblog/2015.html @@ -566,46 +566,45 @@

Evennia Autodocs

Following the big library merger I sat down to write a more comprehensive autodoc utility. We had been distributing a Doxygen config file with the repo for a long time, but I wanted something that integrated with our github wiki, using markdown in the source (because frankly, while Sphinx produces very pretty output, ReST markup looks really ugly in source code, in my opinion).

The result was the api2md program, which is now a part of our wiki repository. It allows our source code to be decorated in "Google style", very readable output:

-

-def funcname(a, b, c, d=False):  """  
+
def funcname(a, b, c, d=False):  """  
 
-    This is a brief introduction to the
+    This is a brief introduction to the
 
-    function/class/method  
+    function/class/method  
 
-  
+  
 
-    Args:  
+    Args:  
 
-        a (str): This is a string argument that
+        a (str): This is a string argument that
 
-          we can talk about over multiple lines.  
+          we can talk about over multiple lines.  
 
-        b (int or str): Another argument  
+        b (int or str): Another argument  
 
-        c (list): A list argument  
+        c (list): A list argument  
 
-        d (bool, optional): An optional keyword argument  
+        d (bool, optional): An optional keyword argument  
 
-  
+  
 
-    Returns:  
+    Returns:  
 
-        str: The result of the function  
+        str: The result of the function  
 
-  
+  
 
-    Notes:  
+    Notes:  
 
-        This is an example function. If `d=True`, something 
+        This is an example function. If `d=True`, something 
 
-        amazing will happen.  
+        amazing will happen.  
 
-  
+  
 
-    """
+    """
+
-

This will be parsed and converted to a Markdown entry and put into the Github wiki, one page per module. The result is the automatically generated Evennia API autodocs, reachable as any other wiki page.

The convertion/prettification of all core functions of Evennia to actually use the Google-style docstrings took almost all year, finishing late in autumn. But now almost all of Evennia uses this style. Coincidentally this also secures us at a 45% comment/code ratio. This places us in the top 10% of well-documented open-source projects according to openhub (gotta love statistics).

Imaginary realities / Optional Realities

@@ -1079,16 +1078,15 @@ def funcname(a, b, c, d=False): """

Evennia as a Python library package

Evennia has until now been solely distributed as a version controlled source tree (first under SVN, then Mercurial and now via GIT and Github). In its current inception you clone the tree and find inside it a game/ directory where you create your game. A problem we have when helping newbies is that we can't easily put pre-filled templates in there - if people used them there might be merge conflicts when we update the templates upstream. So the way people configure Evennia is to make copies of template modules and then change the settings to point to that copy rather than the default module. This works well but it means a higher threshold of setup for new users and a lot of describing text. Also, while learning GIT is a useful skill, it's another hurdle to get past for those who just want to change something minor to see if Evennia is for them.

In the devel branch, Evennia is now a library. The game/ folder is no longer distributed as part of the repository but is created dynamically by using the new binary evennia launcher program, which is also responsible for creating (or migrating) the database as well as operating the server:

-

-evennia --init mygame  
+
evennia --init mygame  
 
 cd mygame  
 
 evennia migrate  
 
 evennia start
+
-

Since this new folder is not under our source tree, we can set up and copy pre-made template modules to it that people can just immediately start filling in without worrying about merge conflicts. We can also dynamically create a setting file that fits the environment as well as set up a correct tree for overloading web functionality and so on. It also makes it a lot easier for people wanting to create multiple games and to put their work under separate version control.

Rather than traversing the repository structure as before you henceforth will just do import evennia in your code to have access to the entirety of the API. And finally this means it will (eventually) be possible to install Evennia from pypi with something like pip install evennia. This will greatly ease the first steps for those not keen on learning GIT.

For existing users

diff --git a/devblog/2016.html b/devblog/2016.html index 25560c040e..705a49c473 100644 --- a/devblog/2016.html +++ b/devblog/2016.html @@ -797,14 +797,16 @@

The MonitorHandler

evennia.MONITOR_HANDLER is the new singleton managing monitoring of on-object field/attribute changes. It is used like this:

-
MONITOR_HANDLER.add(obj, field_or_attrname, callback, **kwargs)
-
+
MONITOR_HANDLER.add(obj, field_or_attrname, callback, **kwargs)
+
+

Here obj is a database entity, like a Character or another Object. The field_or_attrname is a string giving the name of a db_* database field (like "db_key", "db_location" etc). Any name not starting with db_ is assumed to be the name of an on-object Attribute (like "health"). Henceforth, whenever this field or attribute changes in any way (that is, whenever it is re-saved to the database), the callback will be called with the optional kwargs, as well as a way to easily get to the changed value. As all handlers you can also list and remove monitors using the standard MONITOR_HANDLER.remove(), .all() etc.

The TickerHandler

evennia.TICKER_HANDLER should be familiar to Evennia users from before - it's been around for a good while. It allows for creating arbitrary "tickers" that is being "subscribed" to - one ticker will call all subscribers rather than each object or function having its own timer.

Before, the syntax for adding a new ticker required you specify a typeclassed entity and the name of the method on it to call every N seconds. This will now change. This is the new callsign for creating a new ticker:

-
TICKER_HANDLER.add(interval, callback, idstring="", persistent=True, *args, **kwargs)
-
+
TICKER_HANDLER.add(interval, callback, idstring="", persistent=True, *args, **kwargs)
+
+

Here**, interval,** like before, defines how often to call **callback(*args, kwargs).

The big change here is that callback should be given as a valid, already imported callable, which can be either an on-entity method (like obj.func) or a global function in any module (like world.test.func) - the TickerHandler will analyze it and internally store it properly.

idstring works as before, to separate tickers with the same intervals. Finally persistent=False means the ticker will behave the same way a Script with persistent=False does: it will survive a server reload but will not survive a server shutdown. This latter functionality is particularly useful for client-side commands since the client Session will also not survive a shutdown.

diff --git a/devblog/2017.html b/devblog/2017.html index efc24943a2..9d039605e8 100644 --- a/devblog/2017.html +++ b/devblog/2017.html @@ -817,38 +817,37 @@

Next I added one new migration in the Account app - this is the migration that copies the data from the player to the equivalent account-named copies in the database. Since Player will not exist if you run this from scratch you have to make sure that the Player model exists at that point in the migration chain. You can't just do this with a normal import and traceback, you need to use the migration infrastructure. This kind of check works:

-

-  # ...  
+
  # ...  
 
  
 
-  def forwards(apps, schema_editor):  
+  def forwards(apps, schema_editor):  
 
-      try:  
+      try:  
 
-          PlayerDB = apps.get_model("players", "PlayerDB")  
+          PlayerDB = apps.get_model("players", "PlayerDB")  
 
-      except LookupError:  
+      except LookupError:  
 
-          return  
+          return  
 
  
 
-      # copy data from player-tables to database tables here  
+      # copy data from player-tables to database tables here  
 
  
 
- class Migrations(migrations.Migration):  
+ class Migrations(migrations.Migration):  
 
-     # ...  
+     # ...  
 
-     operations = [  
+     operations = [  
 
-         migrations.RunPython(forwards, migrations.RunPython.noop)  
+         migrations.RunPython(forwards, migrations.RunPython.noop)  
 
      ]  
+
-
-

- from django.db import connection  
+
 from django.db import connection  
 
   
 
-    # ...  
+    # ...  
 
   
 
-    def _table_exists(db_cursor, tablename):  
+    def _table_exists(db_cursor, tablename):  
 
-        "Returns bool if table exists or not"  
+        "Returns bool if table exists or not"  
 
-        sql_check_exists = "SELECT * from %s;" % tablename  
+        sql_check_exists = "SELECT * from %s;" % tablename  
 
-    ### [Renaming Django's Auth User and App](https://evennia.blogspot.com/2017/08/renaming-djangos-auth-user-and-app.html)
+    ### [Renaming Django's Auth User and App](https://evennia.blogspot.com/2017/08/renaming-djangos-auth-user-and-app.html)
+
-

And with this, the migration's design was complete. Below is how to actually use it ...

Running the final migration

diff --git a/devblog/2018.html b/devblog/2018.html index 291efad4ad..9fc97404cd 100644 --- a/devblog/2018.html +++ b/devblog/2018.html @@ -585,12 +585,11 @@

In our development branch I've just pushed the first version of the new OLC (OnLine Creator) system. This is a system to allow builders (who may have limited coding knowledge) to customize and spawn new in-game objects more easily without code access. It's started with the olc command in-game. This is a visual system for manipulating Evennia Prototypes.

Briefly on Prototypes

The Prototype is an Evennia concept that has been around a good while. The prototype is a Python dictionary that holds specific keys with values representing properties on a game object. Here's an example of a simple prototype:

-

- {"key": "My house", 
+
 {"key": "My house", 
 
   "typeclass": "typeclasses.houses.MyHouse"}
+
-

By passing this dict to the spawner, a new object named "My house" will be created. It will be set up with the given typeclass (a 'typeclass' is, in Evennia lingo, a Python class with a database backend). A prototype can specify all aspects of an in-game object - its attributes (like description and other game-specific properties), tags, aliases, location and so on. Prototypes also support inheritance - so you can expand on an existing template without having to add everything fresh every time.

There are two main reasons for the Prototypes existing in Evennia: