def test_parsing_timezone(self): """Assert glyphs_datetime can parse the (optional) timezone formatted as UTC offset. If it's not explicitly specified, then +0000 is assumed. """ self.assertEqual( parse_datetime("2017-12-18 16:45:31 -0100"), datetime.datetime(2017, 12, 18, 15, 45, 31), ) self.assertEqual( parse_datetime("2017-12-18 14:15:31 +0130"), datetime.datetime(2017, 12, 18, 15, 45, 31), ) self.assertEqual( parse_datetime("2017-12-18 15:45:31"), datetime.datetime(2017, 12, 18, 15, 45, 31), ) self.assertEqual( parse_datetime("2017-12-18 03:45:31 PM"), datetime.datetime(2017, 12, 18, 15, 45, 31), ) self.assertEqual( parse_datetime("2017-12-18 09:45:31 AM"), datetime.datetime(2017, 12, 18, 9, 45, 31), )
def from_loose_ufo_time(string): """Parses a datetime as specified for UFOs into a datetime object, or as the Glyphs formet.""" try: return from_ufo_time(string) except ValueError: return parse_datetime(string)
def test_set_disable_last_change(self): glyph = GSGlyph() glyph.name = "a" self.font.glyphs.append(glyph) layer = GSLayer() layer.layerId = self.font.masters[0].id layer.associatedMasterId = self.font.masters[0].id layer.width = 100 glyph.layers.append(layer) glyph.lastChange = parse_datetime("2017-10-03 07:35:46 +0000") self.font.customParameters["Disable Last Change"] = True self.ufo = to_ufos(self.font)[0] self.assertEqual( True, self.ufo.lib[FONT_CUSTOM_PARAM_PREFIX + "disablesLastChange"]) self.assertNotIn(GLYPHLIB_PREFIX + "lastChange", self.ufo["a"].lib)
def test_parsing_12hr_format(self): """Assert glyphs_datetime can parse 12 hour time format""" string_12hrs = '2017-01-01 5:30:30 PM +0000' self.assertEqual(parse_datetime(string_12hrs), datetime.datetime(2017, 1, 1, 17, 30, 30))
def test_parsing_24hr_format(self): """Assert glyphs_datetime can parse 24 hour time formats""" string_24hrs = '2017-01-01 17:30:30 +0000' self.assertEqual(parse_datetime(string_24hrs), datetime.datetime(2017, 1, 1, 17, 30, 30))
def test_write_font_attributes(self): """Test the writer on all GSFont attributes""" font = classes.GSFont() # List of properties from https://docu.glyphsapp.com/#gsfont # parent: not handled because it's internal and read-only # masters m1 = classes.GSFontMaster() m1.id = "M1" font.masters.insert(0, m1) m2 = classes.GSFontMaster() m2.id = "M2" font.masters.insert(1, m2) # instances i1 = classes.GSInstance() i1.name = "MuchBold" font.instances.append(i1) # glyphs g1 = classes.GSGlyph() g1.name = 'G1' font.glyphs.append(g1) # classes c1 = classes.GSClass() c1.name = "C1" font.classes.append(c1) # features f1 = classes.GSFeature() f1.name = "F1" font.features.append(f1) # featurePrefixes fp1 = classes.GSFeaturePrefix() fp1 = "FP1" font.featurePrefixes.append(fp1) # copyright font.copyright = "Copyright Bob" # designer font.designer = "Bob" # designerURL font.designerURL = "bob.me" # manufacturer font.manufacturer = "Manu" # manufacturerURL font.manufacturerURL = "manu.com" # versionMajor font.versionMajor = 2 # versionMinor font.versionMinor = 104 # date font.date = parse_datetime('2017-10-03 07:35:46 +0000') # familyName font.familyName = "Sans Rien" # upm font.upm = 2000 # note font.note = "Was bored, made this" # kerning font.kerning = OrderedDict([ ('M1', OrderedDict([ ('@MMK_L_G1', OrderedDict([ ('@MMK_R_G1', 0.1) ])) ])) ]) # userData font.userData = { 'a': 'test', 'b': [1, {'c': 2}], 'd': [1, "1"], 'noodleThickness': "106.0", } # grid -> gridLength font.grid = 35 # gridSubDivisions font.gridSubDivisions = 5 # keyboardIncrement font.keyboardIncrement = 1.2 # disablesNiceNames font.disablesNiceNames = True # customParameters font.customParameters['ascender'] = 300 # selection: not written # selectedLayers: not written # selectedFontMaster: not written # masterIndex: not written # currentText: not written # tabs: not written # currentTab: not written # filepath: not written # tool: not written # tools: not handled because it is a read-only list of GUI features # .appVersion (extra property that is not in the docs!) font.appVersion = "895" self.assertWrites(font, dedent("""\ { .appVersion = "895"; classes = ( { code = ""; name = C1; } ); copyright = "Copyright Bob"; customParameters = ( { name = note; value = "Was bored, made this"; }, { name = ascender; value = 300; } ); date = "2017-10-03 07:35:46 +0000"; designer = Bob; designerURL = bob.me; disablesNiceNames = 1; familyName = "Sans Rien"; featurePrefixes = ( FP1 ); features = ( { code = ""; name = F1; } ); fontMaster = ( { ascender = 800; capHeight = 700; descender = -200; id = M1; xHeight = 500; }, { ascender = 800; capHeight = 700; descender = -200; id = M2; xHeight = 500; } ); glyphs = ( { glyphname = G1; } ); gridLength = 35; gridSubDivision = 5; instances = ( { name = MuchBold; } ); kerning = { M1 = { "@MMK_L_G1" = { "@MMK_R_G1" = 0.1; }; }; }; keyboardIncrement = 1.2; manufacturer = Manu; manufacturerURL = manu.com; unitsPerEm = 2000; userData = { a = test; b = ( 1, { c = 2; } ); d = ( 1, "1" ); noodleThickness = "106.0"; }; versionMajor = 2; versionMinor = 104; } """)) # Don't write the keyboardIncrement if it's 1 (default) font.keyboardIncrement = 1 written = test_helpers.write_to_lines(font) self.assertFalse(any("keyboardIncrement" in line for line in written)) # Always write versionMajor and versionMinor, even when 0 font.versionMajor = 0 font.versionMinor = 0 written = test_helpers.write_to_lines(font) self.assertIn("versionMajor = 0;", written) self.assertIn("versionMinor = 0;", written)
def test_write_glyph(self): glyph = classes.GSGlyph() # https://docu.glyphsapp.com/#gsglyph # parent: not written # layers # Put the glyph in a font with at least one master for the magic in # `glyph.layers.append()` to work. font = classes.GSFont() master = classes.GSFontMaster() master.id = "MASTER-ID" font.masters.insert(0, master) font.glyphs.append(glyph) layer = classes.GSLayer() layer.layerId = "LAYER-ID" layer.name = "L1" glyph.layers.insert(0, layer) # name glyph.name = "Aacute" # unicode glyph.unicode = "00C1" # string: not written # id: not written # category glyph.category = "Letter" # subCategory glyph.subCategory = "Uppercase" # script glyph.script = "latin" # productionName glyph.productionName = "Aacute.prod" # glyphInfo: not written # leftKerningGroup glyph.leftKerningGroup = "A" # rightKerningGroup glyph.rightKerningGroup = "A" # leftKerningKey: not written # rightKerningKey: not written # leftMetricsKey glyph.leftMetricsKey = "A" # rightMetricsKey glyph.rightMetricsKey = "A" # widthMetricsKey glyph.widthMetricsKey = "A" # export glyph.export = False # color glyph.color = 11 # colorObject: not written # note glyph.note = "Stunning one-bedroom A with renovated acute accent" # selected: not written # mastersCompatible: not stored # userData glyph.userData['rememberToMakeCoffe'] = True # Check that empty collections are written glyph.userData['com.someoneelse.coolsoftware.customdata'] = [ OrderedDict([ ('zero', 0), ('emptyList', []), ('emptyDict', {}), ('emptyString', ""), ]), [], {}, "", "hey", 0, 1, ] # smartComponentAxes axis = classes.GSSmartComponentAxis() axis.name = "crotchDepth" glyph.smartComponentAxes.append(axis) # lastChange glyph.lastChange = parse_datetime('2017-10-03 07:35:46 +0000') self.assertWrites(glyph, dedent("""\ { color = 11; export = 0; glyphname = Aacute; lastChange = "2017-10-03 07:35:46 +0000"; layers = ( { associatedMasterId = "MASTER-ID"; layerId = "LAYER-ID"; name = L1; width = 600; } ); leftKerningGroup = A; leftMetricsKey = A; widthMetricsKey = A; note = "Stunning one-bedroom A with renovated acute accent"; rightKerningGroup = A; rightMetricsKey = A; unicode = 00C1; script = latin; category = Letter; subCategory = Uppercase; userData = { com.someoneelse.coolsoftware.customdata = ( { zero = 0; emptyList = ( ); emptyDict = { }; emptyString = ""; }, ( ), { }, "", hey, 0, 1 ); rememberToMakeCoffe = 1; }; partsSettings = ( { name = crotchDepth; bottomValue = 0; topValue = 0; } ); } """)) # Write the script even when it's an empty string # Same for category and subCategory glyph.script = "" glyph.category = "" glyph.subCategory = "" written = test_helpers.write_to_lines(glyph) self.assertIn('script = "";', written) self.assertIn('category = "";', written) self.assertIn('subCategory = "";', written) # Write double unicodes glyph.unicodes = ['00C1', 'E002'] written = test_helpers.write_to_lines(glyph) self.assertIn('unicode = "00C1,E002";', written)