v1.0.0

language syntax & features for v1.0.0

Describes and specifies the syntax structure, data type literals, language format, and features used within a file or literal string.


assignment glyph legend

glyphassignment typedescription

=

regular

assigns name to value

+l=

lock

assigns name to value and locks name from re-assignment

+h=

hard lock

assigns name to value and locks name from re-assignment, deletion, and unlocking

+m=

map

assigns name to another name's value and follows its value changes

+ml=

map lock

maps name and locks name

+mh=

map hard lock

maps name and hard locks name

Uppercase and Mixed case glyphs are also accepted, but not very clean looking. You may also set letters in the desired order in a file or string to load from and the result is the same (e.g. +hm= instead of +mh=). However, the default is what is described in the legend, and any dump mechanics will follow that default when output to a file or string.

There are also symbols that represent the letter-based glyphs, but those will be retired in the future and are not currently encouraged. The symbols were added as ported support from the older library for migration reasons.

symbol glyphs (older, but still supported)

$= lock $$= hard lock == map $== map lock $$== map hard lock

usage

Examples are demonstrating usage in a file to illustrate the language features. Language features may be used in files and strings to be parsed with maci's load functions (See functions).

Regular Assignment

Assigning names to values. Shows all supported data types accepted, and any maci specific extras

Example file "my.data"

name_str = 'data'
name_int = 1
name_float = 1.0
name_bool = True
name_list = [1,2,3]
name_dict = {'k1': 1}
name_tuple = (1,2,3)
name_set = {1,2,3}
name_none = None
name_bytes = b'data\n'
name_datetime = 2023-12-02 21:48:00
name_iso8601 = 2023-12-02T21:48:00-06:00
name_date = 2023-12-02
name_time = 21:48:00

The extras in this example are the date and time formats being parsed natively with maci returning datetime objects in python. It also accepts milliseconds in the time portions. (hint: date and times in example is an easter egg)

Lock Assignment Glyph

Locking a name to a value. This feature protects against an attribute name from being reassigned. Use the lock assignment glyph to set the lock.

name_str +l= 'data'

During the code's runtime, if this attribute name is ever attempted to be reassigned, it will throw an exception and prevent reassignment. If the exception is caught, the value will remain unchanged.

Exception thrown (See errors)

maci.error.GeneralError: Attribute Name Locked! Cannot be reassigned

If you need to reassign the name to a new value while it is locked, you may utilize the partner method "unlock_attr" to achieve this (See unlock_attr)

You may view all locked names using the "get_locked_list" method (See get_locked_list).

Hard Lock Assignment Glyph

Hard locking a name to a value. This feature protects against an attribute name from being reassigned, deleted, and unlocked. Use the hard lock assignment glyph to set the hard lock. This feature effectively gives you a constant-like ability.

name_str +h= 'data'

During the code's runtime, if this attribute name is ever attempted to be reassigned, deleted, or unlocked it will throw an exception to prevent those changes to the name. If an exception is caught, the name and value will remain unchanged. Once this is set, it is permanent during the code's runtime. The only way to change or remove the attribute name would be to delete the whole maci object.

Exceptions thrown (See errors)

This exception is thrown when attempting to reassign or delete name

maci.error.GeneralError: Attribute Name Hard Locked! Cannot be reassigned, deleted, or unlocked

This exception is thrown when attempting to unlock name. Unlock only searches for locked names, not hard-locked names.

maci.error.GeneralError: Unlock attribute name does not exist in lock! Could not find name to unlock

You may view all hard-locked names using the "get_hard_locked_list" method (See get_hard_locked_list).

A Gotcha, but not really. Something to keep in mind is that any objects that are mutable (e.g. a list, dict, set) can still be updated in-place even if you lock/hard-lock an attribute name. Locking is a feature to protect the attribute name, not the value. Any immutable object must always be re-assigned to a name, hence why locking will protect against that.

Map Assignment Glyph

Mapping a name to another name. This feature allows an attribute name to follow another attribute name's value. Use the map assignment glyph and set the value to be the name of the attribute name you want to follow. This feature effectively gives you a pointer-like ability, especially with python's native optimization features to reference the same object in memory for its immutable data types.

name1 = 'data'
name2 +m= name1

During the code's runtime, if the parent attribute name is ever reassigned or if the object it is assigned to changes, the child attribute name will always update its reference to match the parent. Take note, that the name must already exist to assign a name to follow it. If you wish to follow any other names that are not in a file, you may utilize the "map_attr" method in code to map to names (See map_attr). It is possible to create a chain-like structure of your references as well like so:

name1 = 'data'
name2 +m= name1
name3 +m= name2
name4 +m= name3
name5 +m= name4

In this use case, if the parent name changes its value, all child names will update as well following one after another linked together like a chain.

It is also possible to create a key-ring-like structure of your references as well like so:

name1 = 'data'
name2 +m= name1
name3 +m= name1
name4 +m= name1
name5 +m= name1

In this use case, if the parent name changes its value, all child names will update as well referencing the same parent. This is different from the chain concept where they are not following one after another, and just referencing the same parent, kind of like all keys on a single ring. You can have multiple mapped children to as many parents as you want. Once a name is assigned to another name, that other name will now become a parent. It is possible to have a name be a parent and a child simultaneously, and that is demonstrated in the chain concept.

If you need to release a reference to a name, you may utilize the partner method "unmap_attr" to achieve this (See unmap_attr). This will safely release the reference even if the name is locked. You can also reassign the child to another name or value and that will cause it to detach as well, but if it is locked, then a lock exception with be thrown.

You may view all map references and references in a chain-like view using the following methods:

get_all_maps = Shows all parent and child map references get_parent_maps = Shows all parent map references get_child_maps = Shows all child map references get_parent_map_chains = Shows all parent map references as a chain

Map and Lock Assignment Glyphs

Mapping and locking a name. You may combine certain glyphs to assign multiple features to a name. In this example you can map a child name to a parent name, then also lock that name from being changed. No matter the letter order you choose, maci will always first create the reference map, then lock the name to establish an assigned value before locking.

Example using map and lock

name1 = 'data'
name2 +ml= name1

Example using map and hard lock

name1 = 'data'
name2 +mh= name1

This combo may be desired if you want a name to initially reference another name's value, then to lock it so it is unchanged. Keep in mind though, if the parent name changes, the parent will change, but the child will not and throw an exception. You may unlock or unmap the child name temporarily in code to make any changes to the parent without receiving an exception from the child. If you wish to have the child mapped again, then it first must be unlocked if using a normal lock, then simply re-map with map_attr and then re-lock with lock_attr the child to the parent again. Another reason this combo may be desired is if you have a strict set of rules on names that cannot or should not be changed. This can promote architecting your code more carefully to maintain integrity of the names if certain aspects of your program heavily rely on those attribute names. For example, creating a dependency model using the chain concept where if a top or upper-level name changes via re-assignment, then the children that depend on that data will throw exceptions, which can be indicative to not change that data cause certain points of the program depend on it. Again, this can promote rethinking how the data should be updated more carefully depending on how you design it.

multiline data

Certain data types may be represented over multiple lines in a file or string as well and will be read the same as if in a single line. Data types that support going over multiple lines will be represented in that format from maci's dump functions by default. The behavior can be changed by toggling some of the varying parameters (See functions).

Example list, dict, tuple, set

name_list = [
    1,
    2,
    3
]
name_dict = {
    'k1': 1,
    'k2': 2,
    'k3': 3
}
name_tuple = (
    1,
    2,
    3
)
name_set = {
    1,
    2,
    3
}

This format structure is typically desired for easier readability and that is why it is the default output behavior. This behavior will also automatically handle nested data structures as well, maintaining a clean human-readable format.

All multiline data must have their data enclosed properly by their respective delimiting partner character placing it as the first character on a newline trailing the data like in the example above. maci's dump functions auto-handles the formatting on this for any supported objects it accepts.

You may also represent multi-line string data to be loaded as well using triple-quoted strings. However, this is not the default format representation when using the dump functions for reasons of maintaining the integrity of the original string data. This is due to a multi-line string requiring 2 extra characters added to the string, being a leading and trailing newline character, to maintain maci's parsing format structure. If desired, that behavior can be turned on for the dump functions (See functions).

Example multiline string

name_double_quote_str1 = """
data1
  data2
 data3
"""
name_single_quote_str = '''
data1
  data2
 data3
'''

If this dump behavior is turned on, it will generate your string data into a multi-line format only if it detects newline characters in your string. Upon each newline it detects, it will set the next line of data based on that newline detected. Note: maci will natively load multi-line strings in files.

If your string data contains a matching delimiting triple-quoted string at the start of a newline, it will terminate the read at that point just like python would. However, if it contains an opposite triple-quoted string like single triple-quotes inside of double triple-quotes, maci is smart enough to ignore that. You may also escape it if you need both, see example below.

maci ignores the single triple-quotes and vice versa if encapsulated by opposite quote type

name_str = """
data1
'''data2
data3
"""

Escaping the double triple-quotes

name_str = """
data1
\"""data2
data3
"""

comments

Commenting using the native python "#" syntax is fully supported. Multiline comments using single or double quotes are not currently supported but are targeted to feature and support in the future.

Example comment syntax variations in file

# My comment
data1 = 1 # my comment
data2 = [
    1,
    2, # my comment
    3#my comment
] # my comment
# My comment
# My comment
data3 = (#my comment
    1,
    2,
    3
)#my comment

language syntax

Describes the varying syntax structure and data type literals

assignment structure

maci follows and accepts a very similar and familiar name assignment structure as python, with the exception of adding special glyphs to perform special operations. You may assign names to values using any of the following methods:

Examples are represented using a file

Space before and after "=". Common pep8 style. Default structure from dump function format

name = 'John'

Space before "="

name ='John'

Space after "="

name= 'John'

No Spaces between "="

name='John'

Many Random Spaces

name             =    'John'

Syntax also works for all assignment glyphs

Hard lock with no spaces

name+h='John'

data types

maci parses and supports a very similar experience and representation of primitive data types likened to python using a hybrid parsing concept where maci reads and parses the data to prepare for validation, to then be validated and transformed into a python object leveraging the ast library. The mechanics of how it is parsed are not the same of course, but the native data type representation found in python's basic data types can be written similarly.

maci attempts to keep it as familiar to python as possible to make the usage of data feel natural and not hard to learn if you're already comfortable with python's data types and structure. However, maci may add unique features that python does not have, or lack features that python has.

Accepted data type literals and format

Literal values are expressed as if written in a file or string to be parsed

literaltypedescription

"data"

str

String data in double-quotes

'data'

str

String data in single-quotes

'''data'''

str

String data in single triple-quotes

"""data"""

str

String data in double triple-quotes

1

int

Integer data

10_000

int

Integer data using underscores

1.0

float

Floating point data

True

bool

Boolean data

[1,2,3]

list

List data

{'k1': 1}

dict

Dictionary data

(1,2,3)

tuple

Tuple data

1, 2, 3

tuple

Tuple data without parenthesis

{1,2,3}

set

Set data

None

NoneType

None data

b'data\n'

bytes

Bytes data in single quotes

b"data\n"

bytes

Bytes data in double quotes

b'''data\n'''

bytes

Bytes data in single triple-quotes

b"""data\n"""

bytes

Bytes data in double triple-quotes

2023-12-02 21:48:00

datetime

Datetime data as date and time

2023-12-02 21:48:00.050

datetime

Datetime data as date and time.microseconds

21:48:00 2023-12-02

datetime

Datetime data as time and date

21:48:00.050 2023-12-02

datetime

Datetime data as time.microseconds and date

2023-12-02T21:48:00-06:00

datetime

Datetime data as ISO 8601

2023-12-02

datetime.date

Datetime data as date

21:48:00

datetime.time

Datetime data as time

21:48:00.050

datetime.time

Datetime data as time.microseconds

Accepted string literal prefixes

These are python-specific string literal prefixes that adhere to python's natural handling to produce the same results. maci does not do anything to handle these and is solely handled by the ast library.

literaltypedescription

r"data"

str

Raw prefixed string

b"data"

bytes

Bytes prefixed string

u"\u263A"

str

Unicode prefixed string

rb"data\n"

bytes

Prefixed string with raw and bytes combo

br"data\n"

bytes

Prefixed string with bytes and raw combo

Strings that contain any of the above prefixes can be parsed by maci leveraging the ast library.

f-strings are not currently supported but are targeted to feature and support in the future.

Last updated