AENUM creating class bodies dynamically causes pylint warning - enums
I cannot explain why I get a pylint "<class 'AttributeError'>: 'For' object has no attribute 'targets'" warning when I create enum entries dynamically.
I cannot see any reason for the the warning in my code.
from aenum import IntEnum
class Commands(IntEnum):
_ignore_ = 'Commands index'
_init_ = 'value string'
BEL = 0x07, 'Bell'
Commands = vars()
for index in range(4):
Commands[f'DC{index + 1}'] = 0x11 + index, f'Device Control {index + 1}'
for command in Commands:
print(f"0x{command.value:02X} is {command.string}")
The code works fine but I do NOT expect a warning!
The code is OK the bug was within the toolchain:
https://github.com/PyCQA/pylint/issues/2719
Related
Vala error "unknown type name" using enum from camel
I am writing this code in Vala, using Camel using Camel; [...] MimeParser par = new MimeParser(); [...] par.push_state( MimeParserState.MULTIPART, boundary ); I downloaded the camel-1.2.vapi from github vala-girs (this link), put it in a vapi subdirectory and compiled with valac --vapidir=vapi --includedir=/usr/include/evolution-data-server/camel --pkg camel-1.2 --pkg posix --target-glib=2.32 -o prog prog.vala -X -lcamel-1.2 Compiling I get this error: error: unknown type name "CamelMimeParserState" const gchar* camel_mime_parser_state_to_string (CamelMimeParserState self); Looking the C output code I see that the CamelMimeParserState type is used several times but it is never defined. It should be a simple enum because the camel-1.2.vapi file says: [CCode (cheader_filename = "camel/camel.h", cprefix = "CAMEL_MIME_PARSER_STATE_", has_type_id = false)] public enum MimeParserState { INITIAL, PRE_FROM, FROM, HEADER, BODY, MULTIPART, MESSAGE, PART, END, EOF, PRE_FROM_END, FROM_END, HEADER_END, BODY_END, MULTIPART_END, MESSAGE_END } So why doesn't the C output code simply use an enum as the vapi file says (described by cprefix CAMEL_MIME_PARSER_STATE_)? Is there an error in the .vapi file?
I found the solution. The vapi file is wrong because the cname field is missing. Changing the vapi file adding this cname="camel_mime_parser_state_t": [CCode (cheader_filename = "camel/camel.h", cname="camel_mime_parser_state_t", cprefix = "CAMEL_MIME_PARSER_STATE_", has_type_id = false)] public enum MimeParserState { INITIAL, [...] works correctly.
Where is the ruby function 'powershell' defined?
I am using the msutter DSC module for puppet. While reading through the source code, I come across code like this (in dsc_configuration_provider.rb): def create Puppet.debug "\n" + ps_script_content('set') output = powershell(ps_script_content('set')) Puppet.debug output end What file defines the powershell function or method? Is it a ruby builtin? A puppet builtin? Inherited from a class? I know that it is being used to send text to powershell as a command and gathering results, but I need to see the source code to understand how to improve its error logging for my purposes, because certain powershell errors are being swallowed and no warnings are being printed to the Puppet log. These lines in file dsc_provider_helpers.rb may be relevant: provider.commands :powershell => if File.exists?("#{ENV['SYSTEMROOT']}\\sysnative\\WindowsPowershell\\v1.0\\powershell.exe") "#{ENV['SYSTEMROOT']}\\sysnative\\WindowsPowershell\\v1.0\\powershell.exe" elsif File.exists?("#{ENV['SYSTEMROOT']}\\system32\\WindowsPowershell\\v1.0\\powershell.exe") "#{ENV['SYSTEMROOT']}\\system32\\WindowsPowershell\\v1.0\\powershell.exe" else 'powershell.exe' end Surely this defines where the Powershell executable is located, but gives no indication how it is called and how its return value is derived. Are stdout and stderr combined? Am I given the text output or just the error code? etc.
This is core Puppet logic. When a provider has a command, like commands :powershell => some binary That is hooked up as a function powershell(*args). You can see it with other providers like Chocolatey: commands :chocolatey => chocolatey_command def self.chocolatey_command if Puppet::Util::Platform.windows? # must determine how to get to params in ruby #default_location = $chocolatey::params::install_location || ENV['ALLUSERSPROFILE'] + '\chocolatey' chocopath = ENV['ChocolateyInstall'] || ('C:\Chocolatey' if File.directory?('C:\Chocolatey')) || ('C:\ProgramData\chocolatey' if File.directory?('C:\ProgramData\chocolatey')) || "#{ENV['ALLUSERSPROFILE']}\chocolatey" chocopath += '\bin\choco.exe' else chocopath = 'choco.exe' end chocopath end Then other locations can just call chocolatey like a function with args: chocolatey(*args)
Pebble C TupletCString compile error
I have an issue compiling my pebble watchapp. I am trying to send strings to the Pebbl eJS script on the phone lihe this: Tuplet password_tuple = TupletCString(PASSWORD_KEY, password_str); Tuplet email_tuple = TupletCString(EMAIL_KEY, email_str); The compiler error is: (they both error out like this, this is just one of the lines of output below) ./src/app_test.c:84:25: error: the address of 'email_str' will always evaluate as 'true' [-Werror=address] email_str and password_str are defined at the top of the program, like this: static char email_str[30]; static char password_str[30]; #define PASSWORD_PKEY (int32_t)21 #define EMAIL_PKEY (int32_t)20 Does anyone notice anything wrong with this?
#ismail-badawi answer is very correct. Pebble now recommends that you use dict_write_cstring. dict_write_cstring(&iter, SOME_STRING_KEY, string);
Well it's certainly not obvious, but it turns out it's because TupletCString is a macro, and it'll expand to an expression that contains email_str ? strlen(email_str) + 1 : 0 as a subexpression, and this is what causes the error, because email_str can't be null and so the comparison isn't doing anything. I found this thread on the Pebble forums with an explanation. The suggested fix is to define your own macro that doesn't have a conditional, e.g. #define MyTupletCString(_key, _cstring) \ ((const Tuplet) { .type = TUPLE_CSTRING, .key = _key, .cstring = { .data = _cstring, .length = strlen(_cstring) + 1 }})
How to stop ImageMagick in Ruby (Rmagick) evaluating an # sign in text annotation
In an app I recently built for a client the following code resulted in the variable #nameText being evaluated, and then resulting in an error 'no text' (since the variable doesn't exist). To get around this I used gsub, as per the example below. Is there a way to tell Magick not to evaluate the string at all? require 'RMagick' #image = Magick::Image.read( '/path/to/image.jpg' ).first #nameText = '#SomeTwitterUser' #text = Magick::Draw.new #text.font_family = 'Futura' #text.pointsize = 22 #text.font_weight = Magick::BoldWeight # Causes error 'no text'... # #text.annotate( #image, 0,0,200,54, #nameText ) #text.annotate( #image, 0,0,200,54, #nameText.gsub('#', '\#') )
This is the C code from RMagick that is returning the error: // Translate & store in Draw structure draw->info->text = InterpretImageProperties(NULL, image, StringValuePtr(text)); if (!draw->info->text) { rb_raise(rb_eArgError, "no text"); } It is the call to InterpretImageProperties that is modifying the input text - but it is not Ruby, or a Ruby instance variable that it is trying to reference. The function is defined here in the Image Magick core library: http://www.imagemagick.org/api/MagickCore/property_8c_source.html#l02966 Look a bit further down, and you can see the code: /* handle a '#' replace string from file */ if (*p == '#') { p++; if (*p != '-' && (IsPathAccessible(p) == MagickFalse) ) { (void) ThrowMagickException(&image->exception,GetMagickModule(), OptionError,"UnableToAccessPath","%s",p); return((char *) NULL); } return(FileToString(p,~0,&image->exception)); } In summary, this is a core library feature which will attempt to load text from file (named SomeTwitterUser in your case, I have confirmed this -try it!), and your work-around is probably the best you can do. For efficiency, and minimal changes to input strings, you could rely on the selectivity of the library code and only modify the string if it starts with #: #text.annotate( #image, 0,0,200,54, #name_string.gsub( /^#/, '\#') )
Forcing a package's function to use user-provided function
I'm running into a problem with the MNP package which I've traced to an unfortunate call to deparse (whose maximum width is limited to 500 characters). Background (easily skippable if you're bored) Because mnp uses a somewhat idiosyncratic syntax to allow for varying choice sets (you include cbind(choiceA,choiceB,...) in the formula definition), the left hand side of my formula call is 1700 characters or so when model.matrix.default calls deparse on it. Since deparse supports a maximum width.cutoff of 500 characters, the sapply(attr(t, "variables"), deparse, width.cutoff = 500)[-1L] line in model.matrix.default has as its first element: [1] "cbind(plan1, plan2, plan3, plan4, plan5, plan6, plan7, plan8, plan9, plan10, plan11, plan12, plan13, plan14, plan15, plan16, plan17, plan18, plan19, plan20, plan21, plan22, plan23, plan24, plan25, plan26, plan27, plan28, plan29, plan30, plan31, plan32, plan33, plan34, plan35, plan36, plan37, plan38, plan39, plan40, plan41, plan42, plan43, plan44, plan45, plan46, plan47, plan48, plan49, plan50, plan51, plan52, plan53, plan54, plan55, plan56, plan57, plan58, plan59, plan60, plan61, plan62, plan63, " [2] " plan64, plan65, plan66, plan67, plan68, plan69, plan70, plan71, plan72, plan73, plan74, plan75, plan76, plan77, plan78, plan79, plan80, plan81, plan82, plan83, plan84, plan85, plan86, plan87, plan88, plan89, plan90, plan91, plan92, plan93, plan94, plan95, plan96, plan97, plan98, plan99, plan100, plan101, plan102, plan103, plan104, plan105, plan106, plan107, plan108, plan109, plan110, plan111, plan112, plan113, plan114, plan115, plan116, plan117, plan118, plan119, plan120, plan121, plan122, plan123, " [3] " plan124, plan125, plan126, plan127, plan128, plan129, plan130, plan131, plan132, plan133, plan134, plan135, plan136, plan137, plan138, plan139, plan140, plan141, plan142, plan143, plan144, plan145, plan146, plan147, plan148, plan149, plan150, plan151, plan152, plan153, plan154, plan155, plan156, plan157, plan158, plan159, plan160, plan161, plan162, plan163, plan164, plan165, plan166, plan167, plan168, plan169, plan170, plan171, plan172, plan173, plan174, plan175, plan176, plan177, plan178, plan179, " [4] " plan180, plan181, plan182, plan183, plan184, plan185, plan186, plan187, plan188, plan189, plan190, plan191, plan192, plan193, plan194, plan195, plan196, plan197, plan198, plan199, plan200, plan201, plan202, plan203, plan204, plan205, plan206, plan207, plan208, plan209, plan210, plan211, plan212, plan213, plan214, plan215, plan216, plan217, plan218, plan219, plan220, plan221, plan222, plan223, plan224, plan225, plan226, plan227, plan228, plan229, plan230, plan231, plan232, plan233, plan234, plan235, " [5] " plan236, plan237, plan238, plan239, plan240, plan241, plan242, plan243, plan244, plan245, plan246, plan247, plan248, plan249, plan250, plan251, plan252, plan253, plan254, plan255, plan256, plan257, plan258, plan259, plan260, plan261, plan262, plan263, plan264, plan265, plan266, plan267, plan268, plan269, plan270, plan271, plan272, plan273, plan274, plan275, plan276, plan277, plan278, plan279, plan280, plan281, plan282, plan283, plan284, plan285, plan286, plan287, plan288, plan289, plan290, plan291, " [6] " plan292, plan293, plan294, plan295, plan296, plan297, plan298, plan299, plan300, plan301, plan302, plan303, plan304, plan305, plan306, plan307, plan308, plan309, plan310, plan311, plan312, plan313)" When model.matrix.default tests this against the variables in the data.frame, it returns an error. The problem To get around this, I've written a new deparse function: deparse <- function (expr, width.cutoff = 60L, backtick = mode(expr) %in% c("call", "expression", "(", "function"), control = c("keepInteger", "showAttributes", "keepNA"), nlines = -1L) { ret <- .Internal(deparse(expr, width.cutoff, backtick, .deparseOpts(control), nlines)) paste0(ret,collapse="") } However, when I run mnp again and step through, it returns the same error for the same reason (base::deparse is being run, not my deparse). This is somewhat surprising to me, as what I expect is more typified by this example, where the user-defined function temporarily over-writes the base function: > print <- function() { + cat("user-defined print ran\n") + } > print() user-defined print ran I realize the right way to solve this problem is to rewrite model.matrix.default, but as a tool for debugging I'm curious how to force it to use my deparse and why the anticipated (by me) behavior is not happening here.
The functions fixInNamespace and assignInNamespace are provided to allow editing of existing functions. You could try ... but I will not since mucking with deparse looks too dangerous: assignInNamespace("deparse", function (expr, width.cutoff = 60L, backtick = mode(expr) %in% c("call", "expression", "(", "function"), control = c("keepInteger", "showAttributes", "keepNA"), nlines = -1L) { ret <- .Internal(deparse(expr, width.cutoff, backtick, .deparseOpts(control), nlines)) paste0(ret,collapse="") } , "base") There is an indication on the help page that the use of such functions has restrictions and I would not be surprised that such core function might have additional layers of protection. Since it works via side-effect, you should not need to assign the result.
This is how packages with namespaces search for functions, as described in Section 1.6, Package Namespaces of Writing R Extensions Namespaces are sealed once they are loaded. Sealing means that imports and exports cannot be changed and that internal variable bindings cannot be changed. Sealing allows a simpler implementation strategy for the namespace mechanism. Sealing also allows code analysis and compilation tools to accurately identify the definition corresponding to a global variable reference in a function body. The namespace controls the search strategy for variables used by functions in the package. If not found locally, R searches the package namespace first, then the imports, then the base namespace and then the normal search path.