Module: DataMetaDom::PythonLexer
- Includes:
- DataMetaDom
- Defined in:
- lib/dataMetaDom/python.rb
Overview
Definition for generating Python basic classes that do not relate to serialization layer.
For command line details either check the new method’s source or the README.rdoc file, the usage section.
Defined Under Namespace
Classes: PyRegExRoster
Constant Summary collapse
- INIT_PY_HEADER =
Standard header for every __init__.py file
%q< # see https://docs.python.org/3/library/pkgutil.html # without this, Python will have trouble finding packages that share some common tree off the root from pkgutil import extend_path __path__ = extend_path(__path__, __name__) >
- MODEL_HEADER =
The top of each model file.
%q|# This file is generated by DataMeta DOM. Do not edit manually! # package %s import re from ebay_datameta_core.base import Verifiable, DateTime, Migrator, SemVer from ebay_datameta_core.canned_re import CannedRe # noinspection PyCompatibility from enum import Enum |
Constants included from DataMetaDom
BITSET, BOOL, BOOL_CONV, CANNED_RX, CHAR, CONVS, DATAMETA_LIB, DATETIME, DIMMED_TYPES, DOC, DOC_TARGETS, DTTM_CONV, DTTM_TYPE, END_KW, ENUM, FLOAT, FLOAT4, FLOAT8, FRACT_CONV, FULL_COMPARE, IDENTITY, ID_ONLY_COMPARE, ID_START, INCLUDE, INDENT, INDEX, INT, INT1, INT2, INT4, INT8, INTEGRAL_CONV, JAVA_DOC_TARGET, L, MAPPING, MATCHES, MODEL_LEVEL_TOKENS, NAMESPACE, NO_NAMESPACE, NUMERIC, OPTIONAL_PFX, OPT_DIMMABLE, PACK_SEPARATOR, PLAIN_DOC_TARGET, RAW, RECORD, RECORD_LEVEL_TOKENS, REC_ATTR_KEYWORDS, REQUIRED_PFX, SAME_FULL_SFX, SAME_ID_SFX, SCALE_TYPES, SOURCE_INDENT, STANDARD_TYPES, STRING, TEXT_CONV, TYPE_START, UNIQUE, URL, URL_TYPE, VERSION, VER_KW, WIKI, WIKI_REF_HTML
Instance Method Summary collapse
-
#genPy(model, outRoot) ⇒ Object
Generates Python sources for the model, the “plain” Python part, without fancy dependencies.
Methods included from DataMetaDom
combineNsBase, condenseType, fullTypeName, getParenDimInfo, getterName, help, helpAndVerFirstArg, helpMySqlDdl, #helpOracleDdl, helpPojoGen, helpScalaGen, #migrClass, nsAdjustment, #qualName, setterName, splitNameSpace, uniPath, validNs?
Instance Method Details
#genPy(model, outRoot) ⇒ Object
Generates Python sources for the model, the “plain” Python part, without fancy dependencies.
-
Parameters
-
parser
- instance of Model -
outRoot
- output directory
-
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/dataMetaDom/python.rb', line 84 def genPy(model, outRoot) firstRecord = model.records.values.first @pyPackage, baseName, packagePath = DataMetaDom::PojoLexer::assertNamespace(firstRecord.name) # Next: replace dots with underscores. # The path also adjusted accordingly. # # Rationale for this, quoting PEP 8: # # Package and Module Names # # Modules should have short, all-lowercase names. Underscores can be used in the module name if it improves # readability. Python packages should also have short, all-lowercase names, although the use of underscores # is discouraged. # # Short and all-lowercase names, and improving readability if you have complex system and need long package names, # is "discouraged". Can't do this here, our system is more complicated for strictly religous, "pythonic" Python. # A tool must be enabling, and in this case, this irrational ruling gets in the way. # And dots are a no-no, Python can't find packages with complicated package structures and imports. # # Hence, we opt for long package names with underscores for distinctiveness and readability: @pyPackage = @pyPackage.gsub('.', '_') packagePath = packagePath.gsub('/', '_') destDir = File.join(outRoot, packagePath) FileUtils.mkdir_p destDir # build the package path and create __init__.py files in each package's dir if it's not there. @destDir = packagePath.split(File::SEPARATOR).reduce(outRoot){ |s,v| r = s.empty? ? v : File.join(s, v) # next package dir FileUtils.mkdir_p r # create if not there # create the __init__.py with proper content if it's not there df = File.join(r, '__init__.py'); IO.write(df, INIT_PY_HEADER, mode: 'wb') unless r == outRoot || File.file?(df) r # pass r for the next reduce iteration } vars = OpenStruct.new # for template's local variables. ERB does not make them visible to the binding modelFile = File.join(@destDir, 'model.py') [modelFile].each{|f| FileUtils.rm f if File.file?(f)} IO.write(modelFile, MODEL_HEADER % @pyPackage, mode: 'wb') (model.records.values + model.enums.values).each { |srcE| # it is important that the records render first _, baseName, _ = DataMetaDom::PojoLexer::assertNamespace(srcE.name) pyClassName = baseName case when srcE.kind_of?(DataMetaDom::Record) fields = srcE.fields rxRoster = PyRegExRoster.new eqHashFields = srcE.identity ? srcE.identity.args : fields.keys.sort reqFields = fields.values.select{|f| f.isRequired }.map{|f| f.name} verCalls = reqFields.map{|r| %<if(self.__#{r} is None): missingFields.append("#{r}");>}.join("\n#{INDENT * 2}") fieldVerifications = '' fields.each_key { |k| f = fields[k] dt = f.dataType rxRoster.register(f) if f.regex if f.trgType # Maps: if either the key or the value is verifiable, do it mainVf = model.records[dt.type] # main data type is verifiable trgVf = model.records[f.trgType.type] # target type is verifiable if mainVf || trgVf fieldVerifications << "\n#{INDENT*2}#{!f.isRequired ? "if(self.__#{f.name} is not None):\n#{INDENT*3}" : '' }for k, v in self.__#{f.name}.iteritems():#{mainVf ? 'k.verify();' : ''} #{trgVf ? 'v.verify()' :''}\n" end end if model.records[dt.type] && !f.trgType # maps handled separately fieldVerifications << "\n#{INDENT*2}#{!f.isRequired ? "if(self.__#{f.name} is not None): " : '' }#{f.aggr ? "[v___#{f.name}.verify() for v___#{f.name} in self.__#{f.name} ]" : "self.__#{f.name}.verify()"}" # the Verifiable::verify method reference works just fine, tested it: Java correctly calls the method on the object end } IO::write(File.join(@destDir, 'model.py'), ERB.new(IO.read(File.join(File.dirname(__FILE__), '../../tmpl/python/entity.erb')), $SAFE, '%<>').result(binding), mode: 'ab') when srcE.kind_of?(DataMetaDom::Mappings) # FIXME -- implement!!! when srcE.kind_of?(DataMetaDom::Enum) IO.write(modelFile, %|#{baseName} = Enum("#{baseName}", "#{srcE.rawVals.join(' ')}")\n\n|, mode: 'ab') # # handled below, bundled in one huge file when srcE.kind_of?(DataMetaDom::BitSet) # FIXME -- implement!!! else raise "Unsupported Entity: #{srcE.inspect}" end } end |