问:
TypeError: Cannot read properties of undefined (reading 'filename')
I am new to multer npm package. I have built a form with few text input fields and file upload fields. When I entered all fields and submit, data gets saved and file uploaded, all working fine. But clicked submit directly without uploading files then it gives this error:

TypeError: Cannot read properties of undefined (reading 'filename')

Note: I am using React.js and Node.js mongoDB

Form

```<code><div className={`container ${addEventModule.addEventContainer}`}>
    <form onSubmit={this.addEventHandler} encType="multipart/form-data">
        <div className={addEventModule.addEventForm}>
            <div className={`text-center ${addEventModule.title}`}>
                <h3 style={{ color: '#2557A7'}}>Add Event</h3>
            </div>

            <hr />

            <div className="text-center text-danger" style={this.state.others.errormessage ? {visibility: 'visible'} : {visibility: 'hidden'} }>
                <span>{this.state.others.errormessage}</span>
            </div>

            <div className={addEventModule.addEventBody}>
                <div className={`row ${addEventModule.marginBottom}`}>
                    <div className="col-md-12">
                        <Input type="text" label="Event Name" name="event_name" onchange={ (e) => this.inputChangeHandler(e) } value={this.state.inputs.event_name.value} />
                    </div>
                    <div className="col-md-12">
                        <span className="text-danger">{this.state.inputs.event_name.error === 1 ? this.state.inputs.event_name.errormessage : ''}</span>
                    </div>
                </div>

                <div className={`row ${addEventModule.marginBottom}`}>
                    <div className="col-md-12">
                        <Textarea type="text" label="Event Description" name="event_description" onchange={ (e) => this.inputChangeHandler(e) } value={this.state.inputs.event_description.value} rows="5" />
                    </div>
                    <div className="col-md-12">
                        <span className="text-danger">{this.state.inputs.event_description.error === 1 ? this.state.inputs.event_description.errormessage : ''}</span>
                    </div>
                </div>

                <div className={`row ${addEventModule.marginBottom}`}>
                    <div className="col-md-12">
                        <Input type="date" label="Event Date" name="event_date" onchange={ (e) => this.inputChangeHandler(e) } value={this.state.inputs.event_date.value} />
                    </div>
                    <div className="col-md-12">
                        <span className="text-danger">{this.state.inputs.event_date.error === 1 ? this.state.inputs.event_date.errormessage : ''}</span>
                    </div>
                </div>

                <div className={`row ${addEventModule.marginBottom}`}>
                    <div className="col-md-12">
                        <Input type="file" label="Event Image" name="event_image" onchange={ (e) => this.inputChangeHandler(e) } />
                    </div>
                    <div className="col-md-12">
                        <span className="text-danger">{this.state.inputs.event_image.error === 1 ? this.state.inputs.event_image.errormessage : ''}</span>
                    </div>
                </div>

                <div className={`row ${addEventModule.marginBottom}`}>
                    <div className="col-md-12">
                        <Select label="Event Category" name="event_category" onchange={ (e) => this.inputChangeHandler(e) } value={this.state.inputs.event_category.value} />
                    </div>
                    <div className="col-md-12">
                        <span className="text-danger">{this.state.inputs.event_category.error === 1 ? this.state.inputs.event_category.errormessage : ''}</span>
                    </div>
                </div>

                <div className={`row ${addEventModule.marginBottom}`}>
                    <div className="col-md-12">
                        <div className="form-group">
                            <label className="form-label">Event Enabled</label>
                            <Radio type="radio" name="event_enabled" onchange={ (e) => this.inputChangeHandler(e) } value="Yes" labelValue="Yes" />
                            <Radio type="radio" name="event_enabled" onchange={ (e) => this.inputChangeHandler(e) } value="No" labelValue="No" />
                        </div>
                    </div>
                    <div className="col-md-12">
                        <span className="text-danger">{this.state.inputs.event_enabled.error === 1 ? this.state.inputs.event_enabled.errormessage : ''}</span>
                    </div>
                </div>
            </div>

            <div className={addEventModule.addEventFooter}>
                <div className={`row ${addEventModule.marginBottom}`}>
                    <div className="col-md-12">
                        <Button type="submit">Add Event</Button>
                    </div>
                </div>
            </div>
        </div>
    </form>
</div>
</code>```

onsubmit function

```<code>addEventHandler = (e) => {
    e.preventDefault();

    const event_name = this.state.inputs.event_name.value;
    const event_description = this.state.inputs.event_description.value;
    const event_date = this.state.inputs.event_date.value;
    const event_image = this.state.inputs.event_image.value;
    const event_category = this.state.inputs.event_category.value;
    const event_enabled = this.state.inputs.event_enabled.value;
    const event_featured = 'No';

    const formData = new FormData();
    formData.append('event_name',event_name);
    formData.append('event_description',event_description);
    formData.append('event_date',event_date);
    formData.append('event_image',event_image);
    formData.append('event_category',event_category);
    formData.append('event_enabled',event_enabled);
    formData.append('event_featured',event_featured);

    axios({
        method: 'post',
        url: 'http://localhost:4000/sports-event/add-event',
        data: formData
    }).then( response => {
        if(response.data.code === 0){
            alert(response.data.message);
            const initialStateOthers = {
                ...initialEventState.others
            }
            initialStateOthers['submitRedirect'] = 1;
            this.setState({ ...this.state, others: initialStateOthers });
        }else if(response.data.code === 2){
            let duplicateStateInputs = {
                ...this.state.inputs
            }
            const fieldValue = [this.state.inputs.event_name.value, this.state.inputs.event_description.value,this.state.inputs.event_date.value,this.state.inputs.event_image.value,this.state.inputs.event_category.value,this.state.inputs.event_enabled.value];
            const fieldArray = [this.state.inputs.event_name.type, this.state.inputs.event_description.type,this.state.inputs.event_date.type,this.state.inputs.event_image.type,this.state.inputs.event_category.type,this.state.inputs.event_enabled.type];
            for(let i = 0; i < fieldArray.length; i++){
                if(response.data.field === fieldArray[i]){
                    duplicateStateInputs = empty_field_validation(duplicateStateInputs, fieldArray[i], fieldValue[i], response.data.message);
                }else{
                    duplicateStateInputs = empty_field_validation(duplicateStateInputs, fieldArray[i], fieldValue[i], '');
                }
            }
            this.setState({ ...this.state, inputs: duplicateStateInputs});
        }else{
            const initialStateInputs = {
                ...initialEventState.inputs
            }
            const initialStateOthers = {
                ...initialEventState.others
            }
            initialStateInputs['event_name'].value = this.state.inputs.event_name.value;
            initialStateOthers['errormessage'] = response.data.message;
            this.setState({ ...this.state, inputs: initialStateInputs, others: initialStateOthers });
        }
    }).catch( err => {
        console.log(err);
    });
}
</code>```

Node.js

```<code>    const storage = multer.diskStorage({
    destination: function(req, file, cb){
        cb(null, path.join(__dirname,'../public/Images'));
    },
    filename: function(req, file, cb){
        cb(null, Date.now() + file.originalname);
    }
});

const fileFilter = function(req, file, cb){
    if(file.mimetype === 'image/jpg' || file.mimetype === 'image/jpeg' || file.mimetype === 'image/png'){
        cb(null, true);
    }else{
        cb(null, false);
    }
}

const fileUpload = multer({
    storage: storage,
    fileFilter: fileFilter
}).single('event_image');

router.post('/sports-event/add-event', fileUpload, eventController.addEvent);
</code>```

addEvent Controller

```<code>exports.addEvent = (req, res, next) => {
const event_name =req.body.event_name;
const event_description=req.body.event_description;
const event_date=req.body.event_date;
const event_image=req.file;
const imagePath = 'Images/' + req.file.filename;
const event_category=req.body.event_category;
const event_enabled=req.body.event_enabled;
const event_featured= req.body.event_featured;

// ------------------- Validations -----------------------------
if(Event.check_field_if_empty(event_name) == 1){
    return res.json({
        code: 2,
        message: `Event Name is mandatory`,
        field: 'event_name'
    });
}else if(!Event.event_name_regex(event_name)){
    return res.json({
        code: 2,
        message: `Event name must contain only capitals letters`,
        field: `event_name`
    })
}else if(Event.check_field_if_empty(event_description) === 1){
    return res.json({
        code: 2,
        message: `Event Description is mandatory`,
        field: 'event_description'
    });
}else if(!Event.only_letters_numbers(event_description)){
    return res.json({
        code: 2,
        message: `Event Description must contain only letters and numbers, no special characters`,
        field: 'event_description'
    });
}else if(Event.check_field_if_empty(event_date) === 1){
    return res.json({
        code: 2,
        message: `Event Date is mandatory`,
        field: 'event_date'
    });
}else if(Event.check_field_if_empty(event_image) === 1){
    return res.json({
        code: 2,
        message: `Event Image is mandatory`,
        field: 'event_image'
    });
}else if(Event.check_field_if_empty(event_category) === 1){
    return res.json({
        code: 2,
        message: `Event Category is mandatory`,
        field: 'event_category'
    });
}else if(Event.check_field_if_empty(event_enabled) === 1){
    return res.json({
        code: 2,
        message: `Event Enabled is mandatory`,
        field: 'event_enabled'
    });
}

Event.check_if_events_exists(event_name, event_category).then( response => {
    if(response.length > 0){
        res.json({
            code: 1,
            message: "This Events already exists"
        });
    }else{
        Event.add_event(event_name, event_description, event_date, imagePath, event_category, event_enabled, event_featured).then( response => {
            res.json({
                code: 0,
                message: "Event Added Successfully"
            });
        }).catch( err => {
            return res.json({
                code: 1,
                message: `Error : ${err}`
            });
        });
    }
}).catch( err => {
    return res.json({
        code: 1,
        message: `Error : ${err}`
    });
});
 }
</code>```

The above validations are not working.

答: I too had this error but mine was fixed by changing path.dirname(process.main.filename) to path.dirname(process.mainModule.filename), in my model. although I was using express.</p>

Body:
I am new to multer npm package. I have built a form with few text input fields and file upload fields. When I entered all fields and submit, data gets saved and file uploaded, all working fine. But clicked submit directly without uploading files then it gives this error:

TypeError: Cannot read properties of undefined (reading 'filename')

Note: I am using React.js and Node.js mongoDB

Form

<div className={`container ${addEventModule.addEventContainer}`}>
    <form onSubmit={this.addEventHandler} encType="multipart/form-data">

            <div className={`text-center ${addEventModule.title}`}>

Add Event

                {this.state.others.errormessage}

                <div className={`row ${addEventModule.marginBottom}`}>

                        <Input type="text" label="Event Name" name="event_name" onchange={ (e) => this.inputChangeHandler(e) } value={this.state.inputs.event_name.value} />

                        {this.state.inputs.event_name.error === 1 ? this.state.inputs.event_name.errormessage : ''}

                <div className={`row ${addEventModule.marginBottom}`}>

                        <Textarea type="text" label="Event Description" name="event_description" onchange={ (e) => this.inputChangeHandler(e) } value={this.state.inputs.event_description.value} rows="5" />

                        {this.state.inputs.event_description.error === 1 ? this.state.inputs.event_description.errormessage : ''}

                <div className={`row ${addEventModule.marginBottom}`}>

                        <Input type="date" label="Event Date" name="event_date" onchange={ (e) => this.inputChangeHandler(e) } value={this.state.inputs.event_date.value} />

                        {this.state.inputs.event_date.error === 1 ? this.state.inputs.event_date.errormessage : ''}

                <div className={`row ${addEventModule.marginBottom}`}>

                        <Input type="file" label="Event Image" name="event_image" onchange={ (e) => this.inputChangeHandler(e) } />

                        {this.state.inputs.event_image.error === 1 ? this.state.inputs.event_image.errormessage : ''}

                <div className={`row ${addEventModule.marginBottom}`}>

                        <Select label="Event Category" name="event_category" onchange={ (e) => this.inputChangeHandler(e) } value={this.state.inputs.event_category.value} />

                        {this.state.inputs.event_category.error === 1 ? this.state.inputs.event_category.errormessage : ''}

                <div className={`row ${addEventModule.marginBottom}`}>

                            Event Enabled
                            <Radio type="radio" name="event_enabled" onchange={ (e) => this.inputChangeHandler(e) } value="Yes" labelValue="Yes" />
                            <Radio type="radio" name="event_enabled" onchange={ (e) => this.inputChangeHandler(e) } value="No" labelValue="No" />

                        {this.state.inputs.event_enabled.error === 1 ? this.state.inputs.event_enabled.errormessage : ''}

                <div className={`row ${addEventModule.marginBottom}`}>

                        <Button type="submit">Add Event</Button>

    </form>

onsubmit function

addEventHandler = (e) => {
    e.preventDefault();

    const event_name = this.state.inputs.event_name.value;
    const event_description = this.state.inputs.event_description.value;
    const event_date = this.state.inputs.event_date.value;
    const event_image = this.state.inputs.event_image.value;
    const event_category = this.state.inputs.event_category.value;
    const event_enabled = this.state.inputs.event_enabled.value;
    const event_featured = 'No';

    const formData = new FormData();
    formData.append('event_name',event_name);
    formData.append('event_description',event_description);
    formData.append('event_date',event_date);
    formData.append('event_image',event_image);
    formData.append('event_category',event_category);
    formData.append('event_enabled',event_enabled);
    formData.append('event_featured',event_featured);

    axios({
        method: 'post',
        url: 'http://localhost:4000/sports-event/add-event',
        data: formData
    }).then( response => {
        if(response.data.code === 0){
            alert(response.data.message);
            const initialStateOthers = {
                ...initialEventState.others
            }
            initialStateOthers['submitRedirect'] = 1;
            this.setState({ ...this.state, others: initialStateOthers });
        }else if(response.data.code === 2){
            let duplicateStateInputs = {
                ...this.state.inputs
            }
            const fieldValue = [this.state.inputs.event_name.value, this.state.inputs.event_description.value,this.state.inputs.event_date.value,this.state.inputs.event_image.value,this.state.inputs.event_category.value,this.state.inputs.event_enabled.value];
            const fieldArray = [this.state.inputs.event_name.type, this.state.inputs.event_description.type,this.state.inputs.event_date.type,this.state.inputs.event_image.type,this.state.inputs.event_category.type,this.state.inputs.event_enabled.type];
            for(let i = 0; i < fieldArray.length; i++){
                if(response.data.field === fieldArray[i]){
                    duplicateStateInputs = empty_field_validation(duplicateStateInputs, fieldArray[i], fieldValue[i], response.data.message);
                }else{
                    duplicateStateInputs = empty_field_validation(duplicateStateInputs, fieldArray[i], fieldValue[i], '');
                }
            }
            this.setState({ ...this.state, inputs: duplicateStateInputs});
        }else{
            const initialStateInputs = {
                ...initialEventState.inputs
            }
            const initialStateOthers = {
                ...initialEventState.others
            }
            initialStateInputs['event_name'].value = this.state.inputs.event_name.value;
            initialStateOthers['errormessage'] = response.data.message;
            this.setState({ ...this.state, inputs: initialStateInputs, others: initialStateOthers });
        }
    }).catch( err => {
        console.log(err);
    });
}

Node.js

    const storage = multer.diskStorage({
    destination: function(req, file, cb){
        cb(null, path.join(__dirname,'../public/Images'));
    },
    filename: function(req, file, cb){
        cb(null, Date.now() + file.originalname);
    }
});

const fileFilter = function(req, file, cb){
    if(file.mimetype === 'image/jpg' || file.mimetype === 'image/jpeg' || file.mimetype === 'image/png'){
        cb(null, true);
    }else{
        cb(null, false);
    }
}

const fileUpload = multer({
    storage: storage,
    fileFilter: fileFilter
}).single('event_image');

router.post('/sports-event/add-event', fileUpload, eventController.addEvent);

addEvent Controller

exports.addEvent = (req, res, next) => {
const event_name =req.body.event_name;
const event_description=req.body.event_description;
const event_date=req.body.event_date;
const event_image=req.file;
const imagePath = 'Images/' + req.file.filename;
const event_category=req.body.event_category;
const event_enabled=req.body.event_enabled;
const event_featured= req.body.event_featured;

// ------------------- Validations -----------------------------
if(Event.check_field_if_empty(event_name) == 1){
    return res.json({
        code: 2,
        message: `Event Name is mandatory`,
        field: 'event_name'
    });
}else if(!Event.event_name_regex(event_name)){
    return res.json({
        code: 2,
        message: `Event name must contain only capitals letters`,
        field: `event_name`
    })
}else if(Event.check_field_if_empty(event_description) === 1){
    return res.json({
        code: 2,
        message: `Event Description is mandatory`,
        field: 'event_description'
    });
}else if(!Event.only_letters_numbers(event_description)){
    return res.json({
        code: 2,
        message: `Event Description must contain only letters and numbers, no special characters`,
        field: 'event_description'
    });
}else if(Event.check_field_if_empty(event_date) === 1){
    return res.json({
        code: 2,
        message: `Event Date is mandatory`,
        field: 'event_date'
    });
}else if(Event.check_field_if_empty(event_image) === 1){
    return res.json({
        code: 2,
        message: `Event Image is mandatory`,
        field: 'event_image'
    });
}else if(Event.check_field_if_empty(event_category) === 1){
    return res.json({
        code: 2,
        message: `Event Category is mandatory`,
        field: 'event_category'
    });
}else if(Event.check_field_if_empty(event_enabled) === 1){
    return res.json({
        code: 2,
        message: `Event Enabled is mandatory`,
        field: 'event_enabled'
    });
}

Event.check_if_events_exists(event_name, event_category).then( response => {
    if(response.length > 0){
        res.json({
            code: 1,
            message: "This Events already exists"
        });
    }else{
        Event.add_event(event_name, event_description, event_date, imagePath, event_category, event_enabled, event_featured).then( response => {
            res.json({
                code: 0,
                message: "Event Added Successfully"
            });
        }).catch( err => {
            return res.json({
                code: 1,
                message: `Error : ${err}`
            });
        });
    }
}).catch( err => {
    return res.json({
        code: 1,
        message: `Error : ${err}`
    });
});
 }

The above validations are not working.


来源: stackexchange

问:
Why does my component compile as a container but spirit::x3::int_parser does not?
I have been working on a better understanding of compile time code especially where spirit::x3 is concerned. I have a class my_uuid and it is working fine compiled with x3::rule. But as Iterator is declared outside of the scope, it is only good for std::string::iterator. So I thought I'd just create a component written like x3::int_parser. And as far as I can see, it has exactly the same signature. I've tried putting it in the x3 namespace and including right after the `..\x3\numeric\int.hpp' header thinking there is some good reason, but it evades me.

If I set a break point in my uuid_parser and the int_parser I can see that the int_parser is left alone, called right from the parser sequence. But my parser is wrapped as if it were a container. If I uncomment the parser at line 40, the compiler starts looking for the likes of insert. So, that is even more confusing, why doesn't it compile with the need of insert or move if I leave it as the last component in the sequence?

I seem to be missing something very fundamental here. My question is not how to fix this but what am I missing. Thanks.

```<code>#include<iostream>
#include <vector>

#include <boost/spirit/home/x3.hpp>

#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

namespace x3 = boost::spirit::x3;

struct uuid_parser : x3::parser<uuid_parser> {
    typedef boost::uuids::uuid attribute_type;
    static bool const has_attribute = true;
    static bool const handles_container = false;

    template <typename Iterator, typename Context, typename Attribute>
    bool parse(Iterator& first, Iterator const& last, Context const& context, x3::unused_type, Attribute& uuid) const {
        boost::iterator_range<Iterator> rng;
        auto ret = x3::parse(first, last, x3::raw[*x3::char_("0-9a-fA-F-")], rng);
        try {
            uuid = boost::uuids::string_generator()(rng.begin(), rng.end());
        }
        catch (std::exception& e) {
            boost::ignore_unused(e);
            return false;
        }
        return true;
    }
};
const uuid_parser uuid_ = {};

int main() {
    std::string uuid_str(R"(    id(78461bab-6d7c-48bc-a79a-b716d1ab97cb
    id(9350cf32-7fe5-40d2-8a0d-c7f7562d7a15
    id(bad-9350cf32-7fe5-40d2-8a0d-c7f7562d7a15
)");
    auto first(uuid_str.begin());
    std::vector<boost::uuids::uuid> attr;
    x3::phrase_parse(first, uuid_str.end(), *(x3::lit("id(") >> uuid_), x3::space, attr);
    //x3::phrase_parse(first, uuid_str.end(), *(x3::lit("uid(") >> uuid_ >> ')'), x3::space, attr);
    for (auto& item : attr)
        std::cout << item << std::endl;

    std::string int_str(" x(1) x(2) x(3)"); auto ibegin(int_str.begin());
    std::vector<int> int_vect;
    x3::phrase_parse(ibegin, int_str.end(), *(x3::lit("x(") >> x3::int_ >> ')'), x3::space, int_vect);
    for (auto& item : int_vect)
        std::cout << item << std::endl;
    return 0;
}
</code>```

答:
The confusion is that uuids::uuid looks like a container. You can observe this by adding:

```<code>template <> struct x3::traits::detail::is_container_impl<boost::uuids::uuid> {
    using type = std::false_type;
};
</code>```

Live On Coliru

```<code>#include <iostream>
#include <vector>

#include <boost/spirit/home/x3.hpp>

#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

namespace x3 = boost::spirit::x3;

struct uuid_parser : x3::parser<uuid_parser> {
    using attribute_type = boost::uuids::uuid;
    static bool const has_attribute = true;
    static bool const handles_container = false;

    template <typename Iterator, typename Context, typename Attribute>
    bool parse(Iterator& first, Iterator const& last, Context const& context,
               x3::unused_type, Attribute& uuid) const
    {
        try {
            boost::iterator_range<Iterator> rng;
            auto ret = x3::parse(first, last, x3::raw[*(x3::xdigit | '-')], rng);
            if (ret)
                uuid = boost::uuids::string_generator()(rng.begin(), rng.end());
            return true;
        } catch (std::exception const&) {
            return false;
        }
    }
};

template <> struct x3::traits::detail::is_container_impl<boost::uuids::uuid> {
    using type = std::false_type;
};

int main() {
    const uuid_parser uuid_ = {};
    std::string uuid_str(R"(    uid(78461bab-6d7c-48bc-a79a-b716d1ab97cb)
        uid(9350cf32-7fe5-40d2-8a0d-c7f7562d7a15)
        uid(bad-9350cf32-7fe5-40d2-8a0d-c7f7562d7a15)
    )");

    std::vector<boost::uuids::uuid> vec;
    x3::phrase_parse(uuid_str.begin(), uuid_str.end(), *("uid(" >> uuid_ >> ")"), x3::space, vec);
    for (auto const& item : vec)
        std::cout << item << std::endl;
}
</code>```

Prints

```<code>78461bab-6d7c-48bc-a79a-b716d1ab97cb
9350cf32-7fe5-40d2-8a0d-c7f7562d7a15
</code>```

Add Some Debuggability

Live On Coliru

```<code>auto u = x3::rule<struct _u, boost::uuids::uuid>{"u"} = uuid_;
auto r = x3::rule<struct _r, boost::uuids::uuid>{"r"} = "uid(" >> u >> ")";
x3::phrase_parse(uuid_str.begin(), uuid_str.end(), *r, x3::space, vec);
</code>```

Prints

```<code><r>
  <try>    uid(78461bab-6d7</try>
  <u>
    <try>78461bab-6d7c-48bc-a</try>
    <success>)\n        uid(9350cf</success>
    <attributes>78461bab-6d7c-48bc-a79a-b716d1ab97cb</attributes>
  </u>
  <success>\n        uid(9350cf3</success>
  <attributes>78461bab-6d7c-48bc-a79a-b716d1ab97cb</attributes>
</r>
<r>
  <try>\n        uid(9350cf3</try>
  <u>
    <try>9350cf32-7fe5-40d2-8</try>
    <success>)\n        uid(bad-93</success>
    <attributes>9350cf32-7fe5-40d2-8a0d-c7f7562d7a15</attributes>
  </u>
  <success>\n        uid(bad-935</success>
  <attributes>9350cf32-7fe5-40d2-8a0d-c7f7562d7a15</attributes>
</r>
<r>
  <try>\n        uid(bad-935</try>
  <u>
    <try>bad-9350cf32-7fe5-40</try>
    <fail/>
  </u>
  <fail/>
</r>
78461bab-6d7c-48bc-a79a-b716d1ab97cb
9350cf32-7fe5-40d2-8a0d-c7f7562d7a15
</code>```

Simplify

In fact, as you can see you don't need to use BOOST_SPIRIT_DEFINE, separating instantiation from declaration at all:

Live On Coliru

```<code>#include <iostream>
#include <vector>

#include <boost/spirit/home/x3.hpp>

#include <boost/lexical_cast/try_lexical_convert.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

namespace x3 = boost::spirit::x3;

template <> struct x3::traits::detail::is_container_impl<boost::uuids::uuid> {
    using type = std::false_type;
};

namespace Parser {
    template <typename T> static inline auto as(auto p) {
        return x3::rule<struct _, T>{"as"} = p;
    }

    static inline auto const to_uuid = [](auto& ctx) {
        auto r = _attr(ctx);
        _pass(ctx) = boost::conversion::try_lexical_convert<boost::uuids::uuid>(
            std::string_view{r.begin(), r.end()}, _val(ctx));
    };

    static inline auto const uuid_ =
        as<boost::uuids::uuid>(x3::raw[*(x3::xdigit | '-')][to_uuid]);
} // namespace Parser

int main() {
    std::string uuid_str(R"(    uid(78461bab-6d7c-48bc-a79a-b716d1ab97cb)
        uid(9350cf32-7fe5-40d2-8a0d-c7f7562d7a15)
        uid(bad-9350cf32-7fe5-40d2-8a0d-c7f7562d7a15)
    )");

    std::vector<boost::uuids::uuid> vec;
    x3::phrase_parse(uuid_str.begin(), uuid_str.end(), *("uid(" >> Parser::uuid_ >> ")"), x3::space, vec);
    for (auto const& item : vec)
        std::cout << item << std::endl;
}
</code>```

Prints

```<code>78461bab-6d7c-48bc-a79a-b716d1ab97cb
9350cf32-7fe5-40d2-8a0d-c7f7562d7a15
</code>```

Also, Besides...

You said "Iterator" was hardcoded. In fact, it is. But realize that's used only for explicit template specialization. Nothing prevents you from specializing for several iterator types!

See e.g. You could workaround by manufacturing a correct context type and instantiate that (as well)

Skippers in Boost.Spirit.X3

Boost Spirit x3 not compiling

and probably some more in https://stackoverflow.com/search?tab=newest&q=user%3a85371%20BOOST_SPIRIT_INSTANTIATE

ContentLicense: CC BY-SA 4.0

Body:
I have been working on a better understanding of compile time code especially where spirit::x3 is concerned. I have a class my_uuid and it is working fine compiled with x3::rule. But as Iterator is declared outside of the scope, it is only good for std::string::iterator. So I thought I'd just create a component written like x3::int_parser. And as far as I can see, it has exactly the same signature. I've tried putting it in the x3 namespace and including right after the `..\x3\numeric\int.hpp' header thinking there is some good reason, but it evades me.

If I set a break point in my uuid_parser and the int_parser I can see that the int_parser is left alone, called right from the parser sequence. But my parser is wrapped as if it were a container. If I uncomment the parser at line 40, the compiler starts looking for the likes of insert. So, that is even more confusing, why doesn't it compile with the need of insert or move if I leave it as the last component in the sequence?

I seem to be missing something very fundamental here. My question is not how to fix this but what am I missing. Thanks.

#include<iostream>
#include <vector>

#include <boost/spirit/home/x3.hpp>

#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

namespace x3 = boost::spirit::x3;

struct uuid_parser : x3::parser<uuid_parser> {
    typedef boost::uuids::uuid attribute_type;
    static bool const has_attribute = true;
    static bool const handles_container = false;

    template <typename Iterator, typename Context, typename Attribute>
    bool parse(Iterator& first, Iterator const& last, Context const& context, x3::unused_type, Attribute& uuid) const {
        boost::iterator_range<Iterator> rng;
        auto ret = x3::parse(first, last, x3::raw[*x3::char_("0-9a-fA-F-")], rng);
        try {
            uuid = boost::uuids::string_generator()(rng.begin(), rng.end());
        }
        catch (std::exception& e) {
            boost::ignore_unused(e);
            return false;
        }
        return true;
    }
};
const uuid_parser uuid_ = {};

int main() {
    std::string uuid_str(R"(    id(78461bab-6d7c-48bc-a79a-b716d1ab97cb
    id(9350cf32-7fe5-40d2-8a0d-c7f7562d7a15
    id(bad-9350cf32-7fe5-40d2-8a0d-c7f7562d7a15
)");
    auto first(uuid_str.begin());
    std::vector<boost::uuids::uuid> attr;
    x3::phrase_parse(first, uuid_str.end(), *(x3::lit("id(") >> uuid_), x3::space, attr);
    //x3::phrase_parse(first, uuid_str.end(), *(x3::lit("uid(") >> uuid_ >> ')'), x3::space, attr);
    for (auto& item : attr)
        std::cout << item << std::endl;

    std::string int_str(" x(1) x(2) x(3)"); auto ibegin(int_str.begin());
    std::vector<int> int_vect;
    x3::phrase_parse(ibegin, int_str.end(), *(x3::lit("x(") >> x3::int_ >> ')'), x3::space, int_vect);
    for (auto& item : int_vect)
        std::cout << item << std::endl;
    return 0;
}

Body:
The confusion is that uuids::uuid looks like a container. You can observe this by adding:

template <> struct x3::traits::detail::is_container_impl<boost::uuids::uuid> {
    using type = std::false_type;
};

Live On Coliru

#include <iostream>
#include <vector>

#include <boost/spirit/home/x3.hpp>

#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

namespace x3 = boost::spirit::x3;

struct uuid_parser : x3::parser<uuid_parser> {
    using attribute_type = boost::uuids::uuid;
    static bool const has_attribute = true;
    static bool const handles_container = false;

    template <typename Iterator, typename Context, typename Attribute>
    bool parse(Iterator& first, Iterator const& last, Context const& context,
               x3::unused_type, Attribute& uuid) const
    {
        try {
            boost::iterator_range<Iterator> rng;
            auto ret = x3::parse(first, last, x3::raw[*(x3::xdigit | '-')], rng);
            if (ret)
                uuid = boost::uuids::string_generator()(rng.begin(), rng.end());
            return true;
        } catch (std::exception const&) {
            return false;
        }
    }
};

template <> struct x3::traits::detail::is_container_impl<boost::uuids::uuid> {
    using type = std::false_type;
};

int main() {
    const uuid_parser uuid_ = {};
    std::string uuid_str(R"(    uid(78461bab-6d7c-48bc-a79a-b716d1ab97cb)
        uid(9350cf32-7fe5-40d2-8a0d-c7f7562d7a15)
        uid(bad-9350cf32-7fe5-40d2-8a0d-c7f7562d7a15)
    )");

    std::vector<boost::uuids::uuid> vec;
    x3::phrase_parse(uuid_str.begin(), uuid_str.end(), *("uid(" >> uuid_ >> ")"), x3::space, vec);
    for (auto const& item : vec)
        std::cout << item << std::endl;
}

Prints

78461bab-6d7c-48bc-a79a-b716d1ab97cb
9350cf32-7fe5-40d2-8a0d-c7f7562d7a15

Add Some Debuggability

Live On Coliru

auto u = x3::rule<struct _u, boost::uuids::uuid>{"u"} = uuid_;
auto r = x3::rule<struct _r, boost::uuids::uuid>{"r"} = "uid(" >> u >> ")";
x3::phrase_parse(uuid_str.begin(), uuid_str.end(), *r, x3::space, vec);

Prints

<r>
  <try>    uid(78461bab-6d7</try>
  <u>
    <try>78461bab-6d7c-48bc-a</try>
    <success>)\n        uid(9350cf</success>
    <attributes>78461bab-6d7c-48bc-a79a-b716d1ab97cb</attributes>
  </u>
  <success>\n        uid(9350cf3</success>
  <attributes>78461bab-6d7c-48bc-a79a-b716d1ab97cb</attributes>
</r>
<r>
  <try>\n        uid(9350cf3</try>
  <u>
    <try>9350cf32-7fe5-40d2-8</try>
    <success>)\n        uid(bad-93</success>
    <attributes>9350cf32-7fe5-40d2-8a0d-c7f7562d7a15</attributes>
  </u>
  <success>\n        uid(bad-935</success>
  <attributes>9350cf32-7fe5-40d2-8a0d-c7f7562d7a15</attributes>
</r>
<r>
  <try>\n        uid(bad-935</try>
  <u>
    <try>bad-9350cf32-7fe5-40</try>
    <fail/>
  </u>
  <fail/>
</r>
78461bab-6d7c-48bc-a79a-b716d1ab97cb
9350cf32-7fe5-40d2-8a0d-c7f7562d7a15

Simplify

In fact, as you can see you don't need to use BOOST_SPIRIT_DEFINE, separating instantiation from declaration at all:

Live On Coliru

#include <iostream>
#include <vector>

#include <boost/spirit/home/x3.hpp>

#include <boost/lexical_cast/try_lexical_convert.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

namespace x3 = boost::spirit::x3;

template <> struct x3::traits::detail::is_container_impl<boost::uuids::uuid> {
    using type = std::false_type;
};

namespace Parser {
    template <typename T> static inline auto as(auto p) {
        return x3::rule<struct _, T>{"as"} = p;
    }

    static inline auto const to_uuid = [](auto& ctx) {
        auto r = _attr(ctx);
        _pass(ctx) = boost::conversion::try_lexical_convert<boost::uuids::uuid>(
            std::string_view{r.begin(), r.end()}, _val(ctx));
    };

    static inline auto const uuid_ =
        as<boost::uuids::uuid>(x3::raw[*(x3::xdigit | '-')][to_uuid]);
} // namespace Parser

int main() {
    std::string uuid_str(R"(    uid(78461bab-6d7c-48bc-a79a-b716d1ab97cb)
        uid(9350cf32-7fe5-40d2-8a0d-c7f7562d7a15)
        uid(bad-9350cf32-7fe5-40d2-8a0d-c7f7562d7a15)
    )");

    std::vector<boost::uuids::uuid> vec;
    x3::phrase_parse(uuid_str.begin(), uuid_str.end(), *("uid(" >> Parser::uuid_ >> ")"), x3::space, vec);
    for (auto const& item : vec)
        std::cout << item << std::endl;
}

Prints

78461bab-6d7c-48bc-a79a-b716d1ab97cb
9350cf32-7fe5-40d2-8a0d-c7f7562d7a15

Also, Besides...

You said "Iterator" was hardcoded. In fact, it is. But realize that's used only for explicit template specialization. Nothing prevents you from specializing for several iterator types!

See e.g. You could workaround by manufacturing a correct context type and instantiate that (as well)

Skippers in Boost.Spirit.X3

Boost Spirit x3 not compiling

and probably some more in https://stackoverflow.com/search?tab=newest&q=user%3a85371%20BOOST_SPIRIT_INSTANTIATE


问:
Are Rails ActiveRecord object id's guaranteed to be monotonically increasing?
I'd like to be able to return objects in the order they were created. Obviously I could use the created_at field to do this but this will not work in my test scripts where I have stubbed out Time.zone.now to always return the same time.

Does AR guarantee that the next id will always be greater than the last object or is there the possibility that it will reuse deleted ids. I'm pretty sure that databases offer both types of functionality but what does Rails choose by default?

EDIT:

Testing with the SQLite driver suggest that it is monotonic. Even if I delete all the records in the table, close the session, open the session and create more records the id's of the new records are given id's greater than those of the previous deleted objects. However I don't want to rely on empircal evidence here. If someone has a definitive answer on the design intention of ActiveRecord that would be appreciated.

答: Active Record does an INSERT without specifying the ID then retrieves the ID that it was created with, so I'm guessing this is a database specific setting.</p>

ContentLicense: CC BY-SA 3.0


问:
Javascript: using "!!" in boolean context
Is there any reason to use !!someValue (which is equivalent to Boolean(someValue)) in a boolean context? In other words, in situations like if (someValue) ..., does it make sense to write if (!!someValue) ...?

It hurts my eyes and I think it's redundant, but I want to verify that there aren't any edge cases that require it - because I came across a codebase where this seems to be the default way of checking for truthiness.

Clarification: yes, in the general case !!someValue will convert someValue to a boolean; I'm referring to contexts where the runtime will automatically convert someValue to true or false.

答:
That's a helpful way of converting any data type into boolean; The exact synonym would be:

Boolean(someValue)
```

Some prefer the 'double bang' as being more coincise, while others prefer the classic conversion with Boolean(someValue) for better readability.

So returning to your question, it's most likely redundant in conditions, but it can be handy when needing a conversion from any type to boolean.

Body:
That's a helpful way of converting any data type into boolean; The exact synonym would be:

Boolean(someValue)

Some prefer the 'double bang' as being more coincise, while others prefer the classic conversion with Boolean(someValue) for better readability.

So returning to your question, it's most likely redundant in conditions, but it can be handy when needing a conversion from any type to boolean.


问:
SFINAE not working with member function of template class
I have a template class where I would like to remove a member function if the type satisfies some condition, that, as far as I understand, should be a very basic usage of SFINAE, for example:

```<code>template<class T>
class A
{
public:
    template<typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
    T foo () {
        return 1.23;
    }
};
</code>```

However, this is results in an error "no type named 'type'", like SFINAE was not going on. This however works if foo is a function not member of a class. What is wrong with this implementation?

答:
You're missing a dependent name for the compiler to use for SFINAE. Try something like this instead:

```<code>#include <type_traits>

template<class T>
class A
{
public:
    template<typename Tp = T>
    typename std::enable_if<std::is_floating_point<Tp>::value, Tp>::type
    foo () {
        return 1.23;
    }
};

int main() {
    A<double> a;
    a.foo();
}
</code>```

If the type T is not floating point, the declaration would be malformed (no return type) and the function would not be considered for the overload set.

See it on godbolt.

Body:
I have a template class where I would like to remove a member function if the type satisfies some condition, that, as far as I understand, should be a very basic usage of SFINAE, for example:

template<class T>
class A
{
public:
    template<typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
    T foo () {
        return 1.23;
    }
};

However, this is results in an error "no type named 'type'", like SFINAE was not going on. This however works if foo is a function not member of a class. What is wrong with this implementation?

Body:
You're missing a dependent name for the compiler to use for SFINAE. Try something like this instead:

#include <type_traits>

template<class T>
class A
{
public:
    template<typename Tp = T>
    typename std::enable_if<std::is_floating_point<Tp>::value, Tp>::type
    foo () {
        return 1.23;
    }
};

int main() {
    A<double> a;
    a.foo();
}

If the type T is not floating point, the declaration would be malformed (no return type) and the function would not be considered for the overload set.

See it on godbolt.


问:
In Node.js, If i am writing a long running function should I be using setTimeout
or something else to queue up the rest of my function? and use callbacks or does node handle that automatically?

I imagine that I would need to start my code and if there are other things that  need to occur I should be giving up my functions control to give other events control. Is this the case? Or can i be stingy and node will cut off my function when I have used enough time?

Thanks.

答:
You should put your long running function or the code which takes long to execute into separate process because it can, for example, block other incoming requests while this code/function is executing. From node.js website:

But what about multiple-processor concurrency? Aren't threads
  necessary to scale programs to multi-core computers? You can start new
  processes via child_process.fork() these other processes will be
  scheduled in parallel.

I would suggest to watch these articles/presentations in order to get a bigger picture on this topic:

Understanding the node.js event loop

Understanding event loops and writing great code for Node.js

YUI Theater — Tom Hughes-Croucher: “How to Stop Writing Spaghetti Code” (45 min.)


问:
django error: The value of 'ordering[0]' refers to 'username', which is not an attribute of 'accounts.clinic_staff'
I extended my accounts custom user model using a one-to-one field and it worked fine. But when I tried customizing it to display more info such as the staff_number and location, the following error is returned:

<class 'accounts.admin.staffAdmin'>: (admin.E033) The value of 'ordering[0]' refers to 'username', which is not an attribute of 'accounts.clinic_staff'.

the staffAdmin class doesn't have username listed as a list_display and the clinic_staff is just returning the username. I'm stuck on what to do?

this is my accounts>models.py code:

```<code>from datetime import date
import email
import imp
from pyexpat import model
from tkinter import CASCADE
from tkinter.tix import Tree
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager

class MyAccountManager(BaseUserManager):
    def create_user(self, email, username, password=None,):
        if not email:
            raise ValueError('Email address is required')
        if not username:
            raise ValueError('Username is required')
        user = self.model(
            email=self.normalize_email(email),
            username = username,
        )
        user.set_password(password)
        user.save(using = self.db)
        return user

    def create_superuser(self, email, username, password):
        user = self.create_user(
            email=self.normalize_email(email),
            password = password,
            username = username,
            )
        user.is_admin = True
        user.is_staff = True
        user.is_superuser = True
        user.save(using = self.db)
        return user

class Account(AbstractBaseUser):
    email   = models.EmailField(verbose_name="email", max_length=60, unique=True)
    username = models.CharField(max_length=30, unique=True)
    date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
    last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
    is_admin = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    #is_clinic_staff = models.BooleanField(default=False)
    #staff_number = models.CharField(max_length=10, unique=True)
    is_superuser = models.BooleanField(default=False)  #note for self - these fields are required

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username',]

    objects = MyAccountManager()

    def __str__(self):
        return self.email

    def has_perm(self, perm, obj=None):
        return self.is_admin # note to self - required

    def has_module_perms(self, app_Label):
        return True

class clinic_staff(models.Model):
    staff = models.OneToOneField(Account, on_delete=models.CASCADE)

    location = models.CharField(max_length=255)
    staff_number = models.IntegerField()

    def __str__(self):
        return self.staff.username
</code>```

my accounts admin.py code

```<code>from django.contrib import admin
from .models import clinic_staff
from accounts.models import Account
from accounts.models import clinic_staff
from django.contrib.auth.admin import UserAdmin

class AccountAdmin(UserAdmin):
    list_display = ('email', 'username', 'date_joined', 'last_login', 'is_admin', 'is_staff')
    search_field = ('email', 'username',)
    readonly_field = ('date_joined', 'last_login')
    filter_horizontal = ()
    list_filter = ()
    fieldsets = () # note to self: required field

class staffAdmin(UserAdmin):
    list_display = ('location', 'staff_number')
    search_field = ('location', 'staff_number')
    filter_horizontal = ()
    list_filter = ()
    fieldsets = ()

admin.site.register(Account, AccountAdmin)
admin.site.register(clinic_staff, staffAdmin)

</code>```

答:
ok i see

if you're not in production try to  delete your database

and run

manage.py makemigrations
manage.py  migrate

Body:
I extended my accounts custom user model using a one-to-one field and it worked fine. But when I tried customizing it to display more info such as the staff_number and location, the following error is returned:

<class 'accounts.admin.staffAdmin'>: (admin.E033) The value of 'ordering[0]' refers to 'username', which is not an attribute of 'accounts.clinic_staff'.

the staffAdmin class doesn't have username listed as a list_display and the clinic_staff is just returning the username. I'm stuck on what to do?

this is my accounts>models.py code:

from datetime import date
import email
import imp
from pyexpat import model
from tkinter import CASCADE
from tkinter.tix import Tree
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager

class MyAccountManager(BaseUserManager):
    def create_user(self, email, username, password=None,):
        if not email:
            raise ValueError('Email address is required')
        if not username:
            raise ValueError('Username is required')
        user = self.model(
            email=self.normalize_email(email),
            username = username,
        )
        user.set_password(password)
        user.save(using = self.db)
        return user

    def create_superuser(self, email, username, password):
        user = self.create_user(
            email=self.normalize_email(email),
            password = password,
            username = username,
            )
        user.is_admin = True
        user.is_staff = True
        user.is_superuser = True
        user.save(using = self.db)
        return user

class Account(AbstractBaseUser):
    email   = models.EmailField(verbose_name="email", max_length=60, unique=True)
    username = models.CharField(max_length=30, unique=True)
    date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
    last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
    is_admin = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    #is_clinic_staff = models.BooleanField(default=False)
    #staff_number = models.CharField(max_length=10, unique=True)
    is_superuser = models.BooleanField(default=False)  #note for self - these fields are required

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username',]

    objects = MyAccountManager()

    def __str__(self):
        return self.email

    def has_perm(self, perm, obj=None):
        return self.is_admin # note to self - required

    def has_module_perms(self, app_Label):
        return True

class clinic_staff(models.Model):
    staff = models.OneToOneField(Account, on_delete=models.CASCADE)

    location = models.CharField(max_length=255)
    staff_number = models.IntegerField()

    def __str__(self):
        return self.staff.username

my accounts admin.py code

from django.contrib import admin
from .models import clinic_staff
from accounts.models import Account
from accounts.models import clinic_staff
from django.contrib.auth.admin import UserAdmin

class AccountAdmin(UserAdmin):
    list_display = ('email', 'username', 'date_joined', 'last_login', 'is_admin', 'is_staff')
    search_field = ('email', 'username',)
    readonly_field = ('date_joined', 'last_login')
    filter_horizontal = ()
    list_filter = ()
    fieldsets = () # note to self: required field

class staffAdmin(UserAdmin):
    list_display = ('location', 'staff_number')
    search_field = ('location', 'staff_number')
    filter_horizontal = ()
    list_filter = ()
    fieldsets = ()

admin.site.register(Account, AccountAdmin)
admin.site.register(clinic_staff, staffAdmin)


问:
Why does ambari is showing this kerberos authentication error : AmbariAuthToLocalUserDetailsService
Recently ambari server logs are showing some warnings, We didn't identify any issue yet but logs became unreadable (50 lines/s)

/var/log/ambari-server/ambari-server.log

```<code>02 Jul 2021 18:43:52,514  INFO [ambari-client-thread-792188] AmbariAuthToLocalUserDetailsService:109 - Translated knox/<knox_gateway>@<REALM> to knox using auth-to-local rules during Kerberos authentication.
02 Jul 2021 18:43:52,515  WARN [ambari-client-thread-792188] AmbariAuthToLocalUserDetailsService:143 - Failed find user account for user with username of knox during Kerberos authentication.
02 Jul 2021 18:43:52,516  WARN [ambari-client-thread-792188] AmbariKerberosAuthenticationFilter:149 - Negotiate Header was invalid: Negotiate YIIDl...
org.springframework.security.core.userdetails.UsernameNotFoundException: Failed find user account for user with username of knox during Kerberos authentication.
        at org.apache.ambari.server.security.authentication.kerberos.AmbariAuthToLocalUserDetailsService.createUser(AmbariAuthToLocalUserDetailsService.java:144)
        at org.apache.ambari.server.security.authentication.kerberos.AmbariAuthToLocalUserDetailsService.loadUserByUsername(AmbariAuthToLocalUserDetailsService.java:110)
        at org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider.authenticate(KerberosServiceAuthenticationProvider.java:66)
        at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156)
        at org.springframework.security.kerberos.web.authentication.SpnegoAuthenticationProcessingFilter.doFilter(SpnegoAuthenticationProcessingFilter.java:145)
        at org.apache.ambari.server.security.authentication.kerberos.AmbariKerberosAuthenticationFilter.doFilter(AmbariKerberosAuthenticationFilter.java:167)
        at org.apache.ambari.server.security.authentication.AmbariDelegatingAuthenticationFilter.doFilter(AmbariDelegatingAuthenticationFilter.java:120)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.apache.ambari.server.security.authorization.AmbariUserAuthorizationFilter.doFilter(AmbariUserAuthorizationFilter.java:91)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
        at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
        at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
        at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1478)
        at org.apache.ambari.server.api.MethodOverrideFilter.doFilter(MethodOverrideFilter.java:72)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1478)
        at org.apache.ambari.server.api.AmbariPersistFilter.doFilter(AmbariPersistFilter.java:47)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1478)
        at org.apache.ambari.server.security.AbstractSecurityHeaderFilter.doFilter(AbstractSecurityHeaderFilter.java:125)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1478)
        at org.eclipse.jetty.servlets.UserAgentFilter.doFilter(UserAgentFilter.java:82)
        at org.eclipse.jetty.servlets.GzipFilter.doFilter(GzipFilter.java:294)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1478)
        at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:499)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
        at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:557)
        at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
        at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1086)
        at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:427)
        at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
        at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1020)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
        at org.apache.ambari.server.controller.AmbariHandlerList.processHandlers(AmbariHandlerList.java:212)
        at org.apache.ambari.server.controller.AmbariHandlerList.processHandlers(AmbariHandlerList.java:201)
        at org.apache.ambari.server.controller.AmbariHandlerList.handle(AmbariHandlerList.java:139)
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
        at org.eclipse.jetty.server.Server.handle(Server.java:370)
        at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:494)
        at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:973)
        at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:1035)
        at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:641)
        at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:231)
        at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
        at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:696)
        at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:53)
        at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
        at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
        at java.lang.Thread.run(Thread.java:745)
</code>```

/var/log/ambari-server/ambari-audit.log

```<code>2021-07-02T19:01:16.881+0200, User(null), RemoteIp(xxx.xxx.xxx.xxx), Operation(User login), Roles(
), Status(Failed), Reason(Failed find user account for user with username of knox during Kerberos authentication.)
</code>```

Known issue :
https://issues.apache.org/jira/browse/AMBARI-19767

Ambari version : 2.6.2.2
HDP Version : HDP-2.6.5.1100

答:
The root cause of this issue is when the kerberos authentication is enabled for ambari the logout feature will not work any more.

disabling kerberos authentication on ambari server resolved the issue

```<code>authentication.kerberos.enabled=false
</code>```

Body:
Recently ambari server logs are showing some warnings, We didn't identify any issue yet but logs became unreadable (50 lines/s)

/var/log/ambari-server/ambari-server.log

02 Jul 2021 18:43:52,514  INFO [ambari-client-thread-792188] AmbariAuthToLocalUserDetailsService:109 - Translated knox/<knox_gateway>@<REALM> to knox using auth-to-local rules during Kerberos authentication.
02 Jul 2021 18:43:52,515  WARN [ambari-client-thread-792188] AmbariAuthToLocalUserDetailsService:143 - Failed find user account for user with username of knox during Kerberos authentication.
02 Jul 2021 18:43:52,516  WARN [ambari-client-thread-792188] AmbariKerberosAuthenticationFilter:149 - Negotiate Header was invalid: Negotiate YIIDl...
org.springframework.security.core.userdetails.UsernameNotFoundException: Failed find user account for user with username of knox during Kerberos authentication.
        at org.apache.ambari.server.security.authentication.kerberos.AmbariAuthToLocalUserDetailsService.createUser(AmbariAuthToLocalUserDetailsService.java:144)
        at org.apache.ambari.server.security.authentication.kerberos.AmbariAuthToLocalUserDetailsService.loadUserByUsername(AmbariAuthToLocalUserDetailsService.java:110)
        at org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider.authenticate(KerberosServiceAuthenticationProvider.java:66)
        at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156)
        at org.springframework.security.kerberos.web.authentication.SpnegoAuthenticationProcessingFilter.doFilter(SpnegoAuthenticationProcessingFilter.java:145)
        at org.apache.ambari.server.security.authentication.kerberos.AmbariKerberosAuthenticationFilter.doFilter(AmbariKerberosAuthenticationFilter.java:167)
        at org.apache.ambari.server.security.authentication.AmbariDelegatingAuthenticationFilter.doFilter(AmbariDelegatingAuthenticationFilter.java:120)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.apache.ambari.server.security.authorization.AmbariUserAuthorizationFilter.doFilter(AmbariUserAuthorizationFilter.java:91)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
        at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
        at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
        at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1478)
        at org.apache.ambari.server.api.MethodOverrideFilter.doFilter(MethodOverrideFilter.java:72)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1478)
        at org.apache.ambari.server.api.AmbariPersistFilter.doFilter(AmbariPersistFilter.java:47)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1478)
        at org.apache.ambari.server.security.AbstractSecurityHeaderFilter.doFilter(AbstractSecurityHeaderFilter.java:125)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1478)
        at org.eclipse.jetty.servlets.UserAgentFilter.doFilter(UserAgentFilter.java:82)
        at org.eclipse.jetty.servlets.GzipFilter.doFilter(GzipFilter.java:294)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1478)
        at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:499)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
        at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:557)
        at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
        at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1086)
        at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:427)
        at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
        at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1020)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
        at org.apache.ambari.server.controller.AmbariHandlerList.processHandlers(AmbariHandlerList.java:212)
        at org.apache.ambari.server.controller.AmbariHandlerList.processHandlers(AmbariHandlerList.java:201)
        at org.apache.ambari.server.controller.AmbariHandlerList.handle(AmbariHandlerList.java:139)
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
        at org.eclipse.jetty.server.Server.handle(Server.java:370)
        at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:494)
        at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:973)
        at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:1035)
        at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:641)
        at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:231)
        at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
        at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:696)
        at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:53)
        at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
        at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
        at java.lang.Thread.run(Thread.java:745)

/var/log/ambari-server/ambari-audit.log

2021-07-02T19:01:16.881+0200, User(null), RemoteIp(xxx.xxx.xxx.xxx), Operation(User login), Roles(
), Status(Failed), Reason(Failed find user account for user with username of knox during Kerberos authentication.)

Known issue :
https://issues.apache.org/jira/browse/AMBARI-19767

Ambari version : 2.6.2.2
HDP Version : HDP-2.6.5.1100

Body:
The root cause of this issue is when the kerberos authentication is enabled for ambari the logout feature will not work any more.

disabling kerberos authentication on ambari server resolved the issue

authentication.kerberos.enabled=false


问:
ImageGrab is not accessed by pylance
Looking to use PILLOW (PIL) to do an imagegrab.  The purpose of the imagegrab is to view a box on the screen to see incoming things in a flash game.  I did pip install pillow in my terminal.  I want to put from PIL import imagegrab  When I put that text into where I write my script it says:

"ImageGrab isn't accessed by pylance".

I'm not sure what the issue is with the library for PILLOW or what I should do to fix this.  FYI I'm very new to coding, this is week 1 for me.

Error Code in Visual Studio Code:

答: This is a warning from the static code analyzer PyLance saying you are not using ImageGrab in your code yet (it's an idle import, basically). It shouldn't affect the execution of the code.

Title: ImageGrab is not accessed by pylance


问:
Delphi to Excel - Date Format Issue with German Locale
Using Delphi 2007 - Windows 7 - German(Switzerland) locale.

In my application, I'm displaying a DateTime field with Displayformat as "MMM-YY".

Date 3-Mar-11 is displayed as Mai-11.

When exporting to Excel, application first writes grid data to TXT file and then imports it to Excel using OpenText() API.

Then we apply the grid properties to the cells. Thus, the date column in Excel is applied a NumberFormat = MMM-YY (custom format).

But, in Excel date is displayed as "Mai-YY", because in German the date format in Excel is MMM-JJ.

How do I apply the correct date format from Delphi OR correct Excel behaviour so that I can have a solution across all locales?

答:
Excel and dates are a bit of a muddle. If you stick to using an intermediate file, then you are probably stuck. Excel uses its own date format settings and they may/will differ from the Windows' date format settings. So even if you export using the Windows locale settings, Excel may not behave as expected when it is using a different set of values.

Using automation you can interrogate Excel for its settings.

General recipe for exporting dates to Excel

Be aware of the characters used in Windows date and time settings.

```<code>WindowsYearCharacter: string = 'y';   // Do no localize!
WindowsMonthCharacter: string = 'm';  // Do no localize!
WindowsDayCharacter: string = 'd';    // Do no localize!
WindowsHourCharacter: string = 'h';   // Do no localize!
WindowsMinuteCharacter: string = 'm'; // Do no localize!
</code>```

Please note that the Month and minute character are both a 'm', though for dates it should be uppercased. This is needed when you have a format string that takes both a date and a time. As we export either dates or times, we opted to cater for case-insensitive specification of Windows formats.

Interrogate Excel for its xlYearCode, xlMonthCode, xlDayCode, xlHourCode and xlMinuteCode formatting characters using the International collection.

```<code>ExcelDayChar := ExcelApplication.International[xlDayCode];
</code>```

Convert your Windows locale settings to use the Excel characters.

```<code>ExcelDateFormat := ConvertWindowsLocalDateStringToExcel(ShortDateFormat);
</code>```

This uses the function following below. Please note again that this function can only be used for either a date format or a time format. Adapt as necessary when you need formats combining both date and time.

```<code>function ConvertWindowsLocalDateStringToExcel(const aString: string): string;
begin
  // Year character vervangen :
  Result := StringReplace(aString, UpperCase(WindowsYearCharacter), UpperCase(ExcelYearCharacter), [rfReplaceAll]);
  Result := StringReplace(Result, LowerCase(WindowsYearCharacter), LowerCase(ExcelYearCharacter), [rfReplaceAll]);

  // Month character vervangen :
  Result := StringReplace(Result, UpperCase(WindowsMonthCharacter), UpperCase(ExcelMonthCharacter), [rfReplaceAll]);
  Result := StringReplace(Result, LowerCase(WindowsMonthCharacter), LowerCase(ExcelMonthCharacter), [rfReplaceAll]);

  // Day character vervangen :
  Result := StringReplace(Result, UpperCase(WindowsDayCharacter), UpperCase(ExcelDayCharacter), [rfReplaceAll]);
  Result := StringReplace(Result, LowerCase(WindowsDayCharacter), LowerCase(ExcelDayCharacter), [rfReplaceAll]);
end;
</code>```

Then export your data to Excel and then set the number format for the columns (or rows, or cells) containing dates to use the ExcelDateFormat you determined earlier.

```<code>aRange.NumberFormat := ExcelDateFormat;
</code>```

Where aRange is (an OleVariant with an) Excel Range type.

Body:
Excel and dates are a bit of a muddle. If you stick to using an intermediate file, then you are probably stuck. Excel uses its own date format settings and they may/will differ from the Windows' date format settings. So even if you export using the Windows locale settings, Excel may not behave as expected when it is using a different set of values.

Using automation you can interrogate Excel for its settings.

General recipe for exporting dates to Excel

Be aware of the characters used in Windows date and time settings.

WindowsYearCharacter: string = 'y';   // Do no localize!
WindowsMonthCharacter: string = 'm';  // Do no localize!
WindowsDayCharacter: string = 'd';    // Do no localize!
WindowsHourCharacter: string = 'h';   // Do no localize!
WindowsMinuteCharacter: string = 'm'; // Do no localize!

Please note that the Month and minute character are both a 'm', though for dates it should be uppercased. This is needed when you have a format string that takes both a date and a time. As we export either dates or times, we opted to cater for case-insensitive specification of Windows formats.

Interrogate Excel for its xlYearCode, xlMonthCode, xlDayCode, xlHourCode and xlMinuteCode formatting characters using the International collection.

ExcelDayChar := ExcelApplication.International[xlDayCode];

Convert your Windows locale settings to use the Excel characters.

ExcelDateFormat := ConvertWindowsLocalDateStringToExcel(ShortDateFormat);

This uses the function following below. Please note again that this function can only be used for either a date format or a time format. Adapt as necessary when you need formats combining both date and time.

function ConvertWindowsLocalDateStringToExcel(const aString: string): string;
begin
  // Year character vervangen :
  Result := StringReplace(aString, UpperCase(WindowsYearCharacter), UpperCase(ExcelYearCharacter), [rfReplaceAll]);
  Result := StringReplace(Result, LowerCase(WindowsYearCharacter), LowerCase(ExcelYearCharacter), [rfReplaceAll]);

  // Month character vervangen :
  Result := StringReplace(Result, UpperCase(WindowsMonthCharacter), UpperCase(ExcelMonthCharacter), [rfReplaceAll]);
  Result := StringReplace(Result, LowerCase(WindowsMonthCharacter), LowerCase(ExcelMonthCharacter), [rfReplaceAll]);

  // Day character vervangen :
  Result := StringReplace(Result, UpperCase(WindowsDayCharacter), UpperCase(ExcelDayCharacter), [rfReplaceAll]);
  Result := StringReplace(Result, LowerCase(WindowsDayCharacter), LowerCase(ExcelDayCharacter), [rfReplaceAll]);
end;

Then export your data to Excel and then set the number format for the columns (or rows, or cells) containing dates to use the ExcelDateFormat you determined earlier.

aRange.NumberFormat := ExcelDateFormat;

Where aRange is (an OleVariant with an) Excel Range type.


问:
Why would tee fail to write to stdout?
I typically use tee to receive a piped output data, echo it to standard output, and forward it to the actual intended recipient of the piped data. But sometimes this fails, and I cannot exactly understand why.

I'll try to demonstrate with a series of examples:

$ echo testing with this string | tee
testing with this string
```
<p>So, just echoing some data to <code>tee</code> without arguments, is replicated/printed on the terminal/stdout. Note that this should be <code>tee</code> printing the output, as the output from echo is now "piped"/redirected, and therefore not present in stdout anymore (the same that happens here:</p>
<pre class="lang-none prettyprint-override"><code>$ echo aa | echo bb
bb
</code>```

... i.e. echo aa output got redirected to the next command, - which, being echo b, does not care about the input, and outputs just its own output.)

$ echo testing with this string | tee | python3 -c 'a=1'
$
```
<p>Now here, piping data into <code>tee</code> without arguments, - and then piping, from <code>tee</code>, to a program that does not provide any output to terminal/stdout - prints <em>nothing</em>. I would have expected <code>tee</code> here to duplicate to stdout, and then forward to the next command in the pipeline, but apparently that does not happen.</p>
<hr />
<pre class="lang-none prettyprint-override"><code>$ echo testing with this string | tee /dev/stdout
testing with this string
testing with this string
</code>```

Right, so if we pipe to tee with command line argument /dev/stdout, we get the printout twice - and as concluded earlier, it must be tee that produces both printed lines. That means, that when used without an argument, |tee basically does not open any file for duplicating, and simply forwards what it receives on its input, to its output; but as it is the last in the pipeline, its output is stdout in that case, so we get a single printout.

Here we get double printout, because

tee duplicated its input stream to /dev/stdout due to the argument (which ends up as the first printout); and then

forwarded the same input to its output, which here being stdout (as tee is again last in the pipeline), results with the second printout.

This also would explain why the previous ...| tee | python3 -c 'a=1' did not print anything: tee without arguments did not open any file for duplication, and merely forwarded to next command in the toolchain - and as the next one does not print any output either, no output is generated whatsoever.

Well, if the above understanding is correct, then this:

$ echo testing with this string | tee /dev/stdout | python3 -c 'a=1'
$
```

... should print at least one line (from tee copying to /dev/stdout; the "forwarded" part will end up being "gulped" by the final command as it prints nothing), but it does not.

So, why does this happen - where am I going wrong in my understanding of what tee does?

And how can I use tee, to print to stdout, also when its output is forwarded to a command that doesn't print anything to stdout on its own?

答:
You aren't misunderstanding tee, you're misunderstanding what stdout is. In a pipe, like echo testing | tee | python3 -c 'a=1', the tee command's stdout is not the terminal, it's the pipe going to the python command (and the echo command's stdout is the pipe going to tee).

So tee /dev/stdout sends two copies of its input (on stdin) to the exact same place: its stdout, whether that's the terminal, or a pipe, or whatever.

If you want to send a copy of the input to tee someplace other than down the pipe, you need to send it somewhere other than stdout. Where that is depends on where you actually want to send it (i.e. why you want to copy it).  If you specifically want to send it to the terminal, you could do this:

```<code>echo testing | tee /dev/tty | python3 -c 'a=1'
</code>```

...while if you want to send it to the outer context's stdout (which might or might not be a terminal), you can duplicate the outer context's stdin to a different file descriptor (#3 is handy for this), and then have tee write a copy to that:

```<code>{ echo testing | tee /dev/fd/3 | python3 -c 'a=1'; } 3>&1
</code>```

Yet another option is to redirect it to stderr (aka FD #2, which is also the terminal by default, but redirectable separately from stdout) with tee /dev/fd/2.

Note that the various /dev entries I'm using here are supported by most unixish OSes, but they aren't universal. Check to see what your specific OS provides.

Title: Why would tee fail to write to stdout?

Body:
I typically use tee to receive a piped output data, echo it to standard output, and forward it to the actual intended recipient of the piped data. But sometimes this fails, and I cannot exactly understand why.

I'll try to demonstrate with a series of examples:

$ echo testing with this string | tee
testing with this string

So, just echoing some data to tee without arguments, is replicated/printed on the terminal/stdout. Note that this should be tee printing the output, as the output from echo is now "piped"/redirected, and therefore not present in stdout anymore (the same that happens here:

$ echo aa | echo bb
bb

... i.e. echo aa output got redirected to the next command, - which, being echo b, does not care about the input, and outputs just its own output.)

$ echo testing with this string | tee | python3 -c 'a=1'
$

Now here, piping data into tee without arguments, - and then piping, from tee, to a program that does not provide any output to terminal/stdout - prints nothing. I would have expected tee here to duplicate to stdout, and then forward to the next command in the pipeline, but apparently that does not happen.

$ echo testing with this string | tee /dev/stdout
testing with this string
testing with this string

Right, so if we pipe to tee with command line argument /dev/stdout, we get the printout twice - and as concluded earlier, it must be tee that produces both printed lines. That means, that when used without an argument, |tee basically does not open any file for duplicating, and simply forwards what it receives on its input, to its output; but as it is the last in the pipeline, its output is stdout in that case, so we get a single printout.

Here we get double printout, because

tee duplicated its input stream to /dev/stdout due to the argument (which ends up as the first printout); and then

forwarded the same input to its output, which here being stdout (as tee is again last in the pipeline), results with the second printout.

This also would explain why the previous ...| tee | python3 -c 'a=1' did not print anything: tee without arguments did not open any file for duplication, and merely forwarded to next command in the toolchain - and as the next one does not print any output either, no output is generated whatsoever.

Well, if the above understanding is correct, then this:

$ echo testing with this string | tee /dev/stdout | python3 -c 'a=1'
$

... should print at least one line (from tee copying to /dev/stdout; the "forwarded" part will end up being "gulped" by the final command as it prints nothing), but it does not.

So, why does this happen - where am I going wrong in my understanding of what tee does?

And how can I use tee, to print to stdout, also when its output is forwarded to a command that doesn't print anything to stdout on its own?

Body:
You aren't misunderstanding tee, you're misunderstanding what stdout is. In a pipe, like echo testing | tee | python3 -c 'a=1', the tee command's stdout is not the terminal, it's the pipe going to the python command (and the echo command's stdout is the pipe going to tee).

So tee /dev/stdout sends two copies of its input (on stdin) to the exact same place: its stdout, whether that's the terminal, or a pipe, or whatever.

If you want to send a copy of the input to tee someplace other than down the pipe, you need to send it somewhere other than stdout. Where that is depends on where you actually want to send it (i.e. why you want to copy it).  If you specifically want to send it to the terminal, you could do this:

echo testing | tee /dev/tty | python3 -c 'a=1'

...while if you want to send it to the outer context's stdout (which might or might not be a terminal), you can duplicate the outer context's stdin to a different file descriptor (#3 is handy for this), and then have tee write a copy to that:

{ echo testing | tee /dev/fd/3 | python3 -c 'a=1'; } 3>&1

Yet another option is to redirect it to stderr (aka FD #2, which is also the terminal by default, but redirectable separately from stdout) with tee /dev/fd/2.

Note that the various /dev entries I'm using here are supported by most unixish OSes, but they aren't universal. Check to see what your specific OS provides.


问:
How to enable unicode when compiling using cl.exe from Visual Studio Build Tools?
I'm trying to have unicode characters in WIN32 (winapi, no console) program compiled using cl.exe from Visual Studio Build Tools. I've defined UNICODE and _UNICODE in my program source and also using cmd option, but I still don't get unicode characters. Here is my compilation command line: cl C:\path_to_source\preventShutdown.c kernel32.lib user32.lib /DUNICODE /D_UNICODE /O2 /link /NODEFAULTLIB /ENTRY:wWinMain and my source code:

/*
cl C:\path_to_source\preventShutdown.c kernel32.lib user32.lib /DUNICODE /D_UNICODE /O2 /link /NODEFAULTLIB /ENTRY:wWinMain
*/
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND,UINT,WPARAM,LPARAM);
int WINAPI wWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPWSTR lpCmdLine,int nShowCmd)
{
LPCTSTR windowClassName=TEXT("windowClass"),windowName=TEXT("Zatrzymaj wyłączenie");
WNDCLASS windowClass={0};
windowClass.hInstance=hInstance;
windowClass.hIcon=NULL;
windowClass.hCursor=LoadCursor(NULL,IDC_ARROW);
windowClass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
windowClass.lpszMenuName=NULL;
windowClass.lpszClassName=windowClassName;
windowClass.lpfnWndProc=&WindowProc;
if(!RegisterClass(&windowClass))return -1;
HWND hWnd=NULL;
if(!(hWnd=CreateWindow(windowClassName,windowName,WS_OVERLAPPEDWINDOW|WS_VISIBLE,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,NULL,NULL)))return -2;
MSG msg={0};
int bRet=0;
while((bRet=GetMessage(&msg,NULL,0,0))!=0)
{
 if(-1==bRet)return -3;
 TranslateMessage(&msg);
 DispatchMessage(&msg);
}
ExitProcess((UINT)msg.wParam);
return (int)msg.wParam;
}

LRESULT CALLBACK WindowProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_QUERYENDSESSION:
ShutdownBlockReasonCreate(hWnd,TEXT("Rozpoczęto przez użytkownika"));
break;
case WM_ENDSESSION:
return 0;
break;
default:
return DefWindowProc(hWnd,msg,wParam,lParam);
break;
}
return 0;
}
```

- where path_to_source is real path to source code.

答:
If you really want to use Unicode stuff, then just use Unicode stuff directly (WCHAR strings, W-based APIs, etc). Stay away from all that TCHAR stuff based on UNICODE/_UNICODE altogether, this is not the 1990's anymore.  There is no need to rely on TCHAR anymore (unless you need to support Win9x/ME).

```<code>#include <windows.h>

LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
{
    LPCWSTR windowClassName = L"windowClass", windowName = L"Zatrzymaj wyłączenie";
    WNDCLASSW windowClass = {0};
    windowClass.hInstance = hInstance;
    windowClass.hIcon = NULL;
    windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    windowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    windowClass.lpszMenuName = NULL;
    windowClass.lpszClassName = windowClassName;
    windowClass.lpfnWndProc = &WindowProc;

    if (!RegisterClassW(&windowClass)) return -1;

    HWND hWnd = CreateWindowW(windowClassName, windowName, WS_OVERLAPPEDWINDOW|WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
    if (!hWnd) return -2;

    MSG msg = {0};
    while (GetMessageW(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessageW(&msg);
    }

    return (int)msg.wParam;
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        case WM_QUERYENDSESSION:
            ShutdownBlockReasonCreate(hWnd, L"Rozpoczęto przez użytkownika");
            break;
        case WM_ENDSESSION:
            break;
        default:
            return DefWindowProcW(hWnd, msg, wParam, lParam);
    }
    return 0;
}
</code>```

Body:
I'm trying to have unicode characters in WIN32 (winapi, no console) program compiled using cl.exe from Visual Studio Build Tools. I've defined UNICODE and _UNICODE in my program source and also using cmd option, but I still don't get unicode characters. Here is my compilation command line: cl C:\path_to_source\preventShutdown.c kernel32.lib user32.lib /DUNICODE /D_UNICODE /O2 /link /NODEFAULTLIB /ENTRY:wWinMain and my source code:

/*
cl C:\path_to_source\preventShutdown.c kernel32.lib user32.lib /DUNICODE /D_UNICODE /O2 /link /NODEFAULTLIB /ENTRY:wWinMain
*/
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND,UINT,WPARAM,LPARAM);
int WINAPI wWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPWSTR lpCmdLine,int nShowCmd)
{
LPCTSTR windowClassName=TEXT("windowClass"),windowName=TEXT("Zatrzymaj wyłączenie");
WNDCLASS windowClass={0};
windowClass.hInstance=hInstance;
windowClass.hIcon=NULL;
windowClass.hCursor=LoadCursor(NULL,IDC_ARROW);
windowClass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
windowClass.lpszMenuName=NULL;
windowClass.lpszClassName=windowClassName;
windowClass.lpfnWndProc=&WindowProc;
if(!RegisterClass(&windowClass))return -1;
HWND hWnd=NULL;
if(!(hWnd=CreateWindow(windowClassName,windowName,WS_OVERLAPPEDWINDOW|WS_VISIBLE,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,NULL,NULL)))return -2;
MSG msg={0};
int bRet=0;
while((bRet=GetMessage(&msg,NULL,0,0))!=0)
{
 if(-1==bRet)return -3;
 TranslateMessage(&msg);
 DispatchMessage(&msg);
}
ExitProcess((UINT)msg.wParam);
return (int)msg.wParam;
}

LRESULT CALLBACK WindowProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_QUERYENDSESSION:
ShutdownBlockReasonCreate(hWnd,TEXT("Rozpoczęto przez użytkownika"));
break;
case WM_ENDSESSION:
return 0;
break;
default:
return DefWindowProc(hWnd,msg,wParam,lParam);
break;
}
return 0;
}

- where path_to_source is real path to source code.

Body:
If you really want to use Unicode stuff, then just use Unicode stuff directly (WCHAR strings, W-based APIs, etc). Stay away from all that TCHAR stuff based on UNICODE/_UNICODE altogether, this is not the 1990's anymore.  There is no need to rely on TCHAR anymore (unless you need to support Win9x/ME).

#include <windows.h>

LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
{
    LPCWSTR windowClassName = L"windowClass", windowName = L"Zatrzymaj wyłączenie";
    WNDCLASSW windowClass = {0};
    windowClass.hInstance = hInstance;
    windowClass.hIcon = NULL;
    windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    windowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    windowClass.lpszMenuName = NULL;
    windowClass.lpszClassName = windowClassName;
    windowClass.lpfnWndProc = &WindowProc;

    if (!RegisterClassW(&windowClass)) return -1;

    HWND hWnd = CreateWindowW(windowClassName, windowName, WS_OVERLAPPEDWINDOW|WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
    if (!hWnd) return -2;

    MSG msg = {0};
    while (GetMessageW(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessageW(&msg);
    }

    return (int)msg.wParam;
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        case WM_QUERYENDSESSION:
            ShutdownBlockReasonCreate(hWnd, L"Rozpoczęto przez użytkownika");
            break;
        case WM_ENDSESSION:
            break;
        default:
            return DefWindowProcW(hWnd, msg, wParam, lParam);
    }
    return 0;
}